PageRenderTime 115ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/app/siteinvoice/lib/PEAR/PEAR/Downloader/Package.php

https://github.com/lux/sitellite
PHP | 1605 lines | 1350 code | 46 blank | 209 comment | 358 complexity | adbf3946360600a2f4887772cd943ef6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, GPL-3.0

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

  1. <?php
  2. /**
  3. * PEAR_Downloader_Package
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: This source file is subject to version 3.0 of the PHP license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  10. * the PHP License and are unable to obtain it through the web, please
  11. * send a note to license@php.net so we can mail you a copy immediately.
  12. *
  13. * @category pear
  14. * @package PEAR
  15. * @author Greg Beaver <cellog@php.net>
  16. * @copyright 1997-2005 The PHP Group
  17. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  18. * @version CVS: $Id: Package.php,v 1.1 2005/07/02 21:12:31 lux Exp $
  19. * @link http://pear.php.net/package/PEAR
  20. * @since File available since Release 1.4.0a1
  21. */
  22. /**
  23. * Coordinates download parameters and manages their dependencies
  24. * prior to downloading them.
  25. *
  26. * Input can come from three sources:
  27. *
  28. * - local files (archives or package.xml)
  29. * - remote files (downloadable urls)
  30. * - abstract package names
  31. *
  32. * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
  33. * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
  34. * format returned of dependencies is slightly different from that used in package.xml.
  35. *
  36. * This class hides the differences between these elements, and makes automatic
  37. * dependency resolution a piece of cake. It also manages conflicts when
  38. * two classes depend on incompatible dependencies, or differing versions of the same
  39. * package dependency. In addition, download will not be attempted if the php version is
  40. * not supported, PEAR installer version is not supported, or non-PECL extensions are not
  41. * installed.
  42. * @category pear
  43. * @package PEAR
  44. * @author Greg Beaver <cellog@php.net>
  45. * @copyright 1997-2005 The PHP Group
  46. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  47. * @version Release: 1.4.0a12
  48. * @link http://pear.php.net/package/PEAR
  49. * @since Class available since Release 1.4.0a1
  50. */
  51. class PEAR_Downloader_Package
  52. {
  53. /**
  54. * @var PEAR_Downloader
  55. */
  56. var $_downloader;
  57. /**
  58. * @var PEAR_Config
  59. */
  60. var $_config;
  61. /**
  62. * @var PEAR_Registry
  63. */
  64. var $_registry;
  65. /**
  66. * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
  67. */
  68. var $_packagefile;
  69. /**
  70. * @var array
  71. */
  72. var $_parsedname;
  73. /**
  74. * @var array
  75. */
  76. var $_downloadURL;
  77. /**
  78. * @var array
  79. */
  80. var $_downloadDeps = array();
  81. /**
  82. * @var boolean
  83. */
  84. var $_valid = false;
  85. /**
  86. * @var boolean
  87. */
  88. var $_analyzed = false;
  89. /**
  90. * if this or a parent package was invoked with Package-state, this is set to the
  91. * state variable.
  92. *
  93. * This allows temporary reassignment of preferred_state for a parent package and all of
  94. * its dependencies.
  95. * @var string|false
  96. */
  97. var $_explicitState = false;
  98. /**
  99. * If this package is invoked with Package#group, this variable will be true
  100. */
  101. var $_explicitGroup = false;
  102. /**
  103. * Package type local|url|xmlrpc
  104. * @var string
  105. */
  106. var $_type;
  107. /**
  108. * Contents of package.xml, if downloaded from a remote channel
  109. * @var string|false
  110. * @access private
  111. */
  112. var $_rawpackagefile;
  113. /**
  114. * @var boolean
  115. * @access private
  116. */
  117. var $_validated = false;
  118. /**
  119. * @param PEAR_Config
  120. */
  121. function PEAR_Downloader_Package(&$downloader)
  122. {
  123. $this->_downloader = &$downloader;
  124. $this->_config = &$this->_downloader->config;
  125. $this->_registry = &$this->_config->getRegistry();
  126. $this->_valid = $this->_analyzed = false;
  127. }
  128. /**
  129. * Parse the input and determine whether this is a local file, a remote uri, or an
  130. * abstract package name.
  131. *
  132. * This is the heart of the PEAR_Downloader_Package(), and is used in
  133. * {@link PEAR_Downloader::download()}
  134. * @param string
  135. * @return void|PEAR_Error
  136. */
  137. function initialize($param)
  138. {
  139. $origErr = $this->_fromFile($param);
  140. if (!$this->_valid) {
  141. $options = $this->_downloader->getOptions();
  142. if (isset($options['offline'])) {
  143. if (PEAR::isError($origErr)) {
  144. if (!isset($options['soft'])) {
  145. $this->log(0, $origErr->getMessage());
  146. }
  147. }
  148. return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
  149. }
  150. $err = $this->_fromUrl($param);
  151. if (PEAR::isError($err) || !$this->_valid) {
  152. if ($this->_type == 'url') {
  153. if (PEAR::isError($err)) {
  154. if (!isset($options['soft'])) {
  155. $this->_downloader->log(0, $err->getMessage());
  156. }
  157. }
  158. return PEAR::raiseError("Invalid or missing remote package file");
  159. }
  160. $err = $this->_fromString($param);
  161. if (PEAR::isError($err) || !$this->_valid) {
  162. if (isset($this->_type) && $this->_type == 'local' &&
  163. PEAR::isError($origErr)) {
  164. if (is_array($origErr->getUserInfo())) {
  165. foreach ($origErr->getUserInfo() as $err) {
  166. if (is_array($err)) {
  167. $err = $err['message'];
  168. }
  169. if (!isset($options['soft'])) {
  170. $this->_downloader->log(0, $err);
  171. }
  172. }
  173. }
  174. if (!isset($options['soft'])) {
  175. $this->_downloader->log(0, $origErr->getMessage());
  176. }
  177. if (is_array($param)) {
  178. $param = $this->_registry->parsedPackageNameToString($param,
  179. true);
  180. }
  181. return PEAR::raiseError(
  182. "Cannot initialize '$param', invalid or missing package file");
  183. }
  184. if (PEAR::isError($err)) {
  185. if (!isset($options['soft'])) {
  186. $this->_downloader->log(0, $err->getMessage());
  187. }
  188. }
  189. if (is_array($param)) {
  190. $param = $this->_registry->parsedPackageNameToString($param, true);
  191. }
  192. return PEAR::raiseError(
  193. "Cannot initialize '$param', invalid or missing package file");
  194. }
  195. }
  196. }
  197. }
  198. /**
  199. * Retrieve any non-local packages
  200. * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
  201. */
  202. function &download()
  203. {
  204. if (isset($this->_packagefile)) {
  205. return $this->_packagefile;
  206. }
  207. if (isset($this->_downloadURL['url'])) {
  208. $this->_isvalid = false;
  209. $info = $this->getParsedPackage();
  210. foreach ($info as $i => $p) {
  211. $info[$i] = strtolower($p);
  212. }
  213. $err = $this->_fromUrl($this->_downloadURL['url'],
  214. $this->_registry->parsedPackageNameToString($this->_parsedname, true));
  215. $newinfo = $this->getParsedPackage();
  216. foreach ($newinfo as $i => $p) {
  217. $newinfo[$i] = strtolower($p);
  218. }
  219. if ($info != $newinfo) {
  220. do {
  221. if ($info['package'] == 'pecl.php.net' && $newinfo['package'] == 'pear.php.net') {
  222. $info['package'] = 'pear.php.net';
  223. if ($info == $newinfo) {
  224. // skip the channel check if a pecl package says it's a PEAR package
  225. break;
  226. }
  227. }
  228. return PEAR::raiseError('CRITICAL ERROR: We are ' .
  229. $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
  230. 'downloaded claims to be ' .
  231. $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
  232. } while (false);
  233. }
  234. if (PEAR::isError($err) || !$this->_valid) {
  235. return $err;
  236. }
  237. }
  238. $this->_type = 'local';
  239. return $this->_packagefile;
  240. }
  241. function &getPackageFile()
  242. {
  243. return $this->_packagefile;
  244. }
  245. function &getDownloader()
  246. {
  247. return $this->_downloader;
  248. }
  249. function getType()
  250. {
  251. return $this->_type;
  252. }
  253. /**
  254. * Like {@link initialize()}, but operates on a dependency
  255. */
  256. function fromDepURL($dep)
  257. {
  258. $this->_downloadURL = $dep;
  259. if (isset($dep['uri'])) {
  260. $options = $this->_downloader->getOptions();
  261. if (!extension_loaded("zlib") || isset($options['nocompress'])) {
  262. $ext = '.tar';
  263. } else {
  264. $ext = '.tgz';
  265. }
  266. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  267. $err = $this->_fromUrl($dep['uri'] . $ext);
  268. PEAR::popErrorHandling();
  269. if (PEAR::isError($err)) {
  270. if (!isset($options['soft'])) {
  271. $this->_downloader->log(0, $err->getMessage());
  272. }
  273. return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
  274. 'cannot download');
  275. }
  276. } else {
  277. $this->_parsedname =
  278. array(
  279. 'package' => $dep['info']->getPackage(),
  280. 'channel' => $dep['info']->getChannel(),
  281. 'version' => $dep['version']
  282. );
  283. if (!isset($dep['nodefault'])) {
  284. $this->_parsedname['group'] = 'default'; // download the default dependency group
  285. $this->_explicitGroup = false;
  286. }
  287. $this->_rawpackagefile = $dep['raw'];
  288. }
  289. }
  290. function detectDependencies($params)
  291. {
  292. $options = $this->_downloader->getOptions();
  293. if (isset($options['downloadonly'])) {
  294. return;
  295. }
  296. if (isset($options['offline'])) {
  297. $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
  298. return;
  299. }
  300. $pname = $this->getParsedPackage();
  301. if (!$pname) {
  302. return;
  303. }
  304. $deps = $this->getDeps();
  305. if (!$deps) {
  306. return;
  307. }
  308. if (isset($deps['required'])) { // package.xml 2.0
  309. return $this->_detect2($deps, $pname, $options, $params);
  310. } else {
  311. return $this->_detect1($deps, $pname, $options, $params);
  312. }
  313. }
  314. function setValidated()
  315. {
  316. $this->_validated = true;
  317. }
  318. function alreadyValidated()
  319. {
  320. return $this->_validated;
  321. }
  322. /**
  323. * Remove packages to be downloaded that are already installed
  324. * @param array of PEAR_Downloader_Package objects
  325. * @static
  326. */
  327. function removeInstalled(&$params)
  328. {
  329. if (!isset($params[0])) {
  330. return;
  331. }
  332. $options = $params[0]->_downloader->getOptions();
  333. if (!isset($options['downloadonly'])) {
  334. foreach ($params as $i => $param) {
  335. // remove self if already installed with this version
  336. // this does not need any pecl magic - we only remove exact matches
  337. if ($param->_registry->packageExists($param->getPackage(), $param->getChannel())) {
  338. if (version_compare($param->_registry->packageInfo($param->getPackage(), 'version',
  339. $param->getChannel()), $param->getVersion(), '==')) {
  340. if (!isset($options['force'])) {
  341. $info = $param->getParsedPackage();
  342. unset($info['version']);
  343. unset($info['state']);
  344. if (!isset($options['soft'])) {
  345. $param->_downloader->log(1, 'Skipping package "' .
  346. $param->getShortName() .
  347. '", already installed as version ' . $param->getVersion());
  348. }
  349. $params[$i] = false;
  350. }
  351. } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
  352. !isset($options['soft'])) {
  353. $info = $param->getParsedPackage();
  354. $param->_downloader->log(1, 'Skipping package "' .
  355. $param->getShortName() .
  356. '", already installed as version ' . $param->getVersion());
  357. $params[$i] = false;
  358. }
  359. }
  360. }
  361. }
  362. PEAR_Downloader_Package::removeDuplicates($params);
  363. }
  364. function _detect2($deps, $pname, $options, $params)
  365. {
  366. $this->_downloadDeps = array();
  367. $groupnotfound = false;
  368. foreach (array('package', 'subpackage') as $packagetype) {
  369. // get required dependency group
  370. if (isset($deps['required'][$packagetype])) {
  371. if (isset($deps['required'][$packagetype][0])) {
  372. foreach ($deps['required'][$packagetype] as $dep) {
  373. if (isset($dep['conflicts'])) {
  374. // skip any package that this package conflicts with
  375. continue;
  376. }
  377. $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
  378. if (is_array($ret)) {
  379. $this->_downloadDeps[] = $ret;
  380. }
  381. }
  382. } else {
  383. $dep = $deps['required'][$packagetype];
  384. if (!isset($dep['conflicts'])) {
  385. // skip any package that this package conflicts with
  386. $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
  387. if (is_array($ret)) {
  388. $this->_downloadDeps[] = $ret;
  389. }
  390. }
  391. }
  392. }
  393. // get optional dependency group, if any
  394. if (isset($deps['optional'][$packagetype])) {
  395. $skipnames = array();
  396. if (!isset($deps['optional'][$packagetype][0])) {
  397. $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
  398. }
  399. foreach ($deps['optional'][$packagetype] as $dep) {
  400. $skip = false;
  401. if (!isset($options['alldeps'])) {
  402. $dep['package'] = $dep['name'];
  403. if (!isset($options['soft'])) {
  404. $this->_downloader->log(3, 'Notice: package "' .
  405. $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
  406. true) . '" optional dependency "' .
  407. $this->_registry->parsedPackageNameToString(array('package' =>
  408. $dep['name'], 'channel' => 'pear.php.net'), true) .
  409. '" will not be automatically downloaded');
  410. }
  411. $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
  412. $skip = true;
  413. unset($dep['package']);
  414. }
  415. if (!($ret = $this->_detect2Dep($dep, $pname, 'optional', $params))) {
  416. $dep['package'] = $dep['name'];
  417. if (@$skipnames[count($skipnames) - 1] ==
  418. $this->_registry->parsedPackageNameToString($dep, true)) {
  419. array_pop($skipnames);
  420. }
  421. }
  422. if (!$skip && is_array($ret)) {
  423. $this->_downloadDeps[] = $ret;
  424. }
  425. }
  426. if (count($skipnames)) {
  427. if (!isset($options['soft'])) {
  428. $this->_downloader->log(1, 'Did not download optional dependencies: ' .
  429. implode(', ', $skipnames) .
  430. ', use --alldeps to download automatically');
  431. }
  432. }
  433. }
  434. // get requested dependency group, if any
  435. $groupname = $this->getGroup();
  436. $explicit = $this->_explicitGroup;
  437. if (!$groupname) {
  438. if ($this->canDefault()) {
  439. $groupname = 'default'; // try the default dependency group
  440. } else {
  441. continue;
  442. }
  443. }
  444. if ($groupnotfound) {
  445. continue;
  446. }
  447. if (isset($deps['group'])) {
  448. if (isset($deps['group']['attribs'])) {
  449. if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
  450. $group = $deps['group'];
  451. } elseif ($explicit) {
  452. if (!isset($options['soft'])) {
  453. $this->_downloader->log(0, 'Warning: package "' .
  454. $this->_registry->parsedPackageNameToString($pname, true) .
  455. '" has no dependency ' . 'group named "' . $groupname . '"');
  456. }
  457. $groupnotfound = true;
  458. continue;
  459. }
  460. } else {
  461. $found = false;
  462. foreach ($deps['group'] as $group) {
  463. if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
  464. $found = true;
  465. break;
  466. }
  467. }
  468. if (!$found) {
  469. if ($explicit) {
  470. if (!isset($options['soft'])) {
  471. $this->_downloader->log(0, 'Warning: package "' .
  472. $this->_registry->parsedPackageNameToString($pname, true) .
  473. '" has no dependency ' . 'group named "' . $groupname . '"');
  474. }
  475. }
  476. $groupnotfound = true;
  477. continue;
  478. }
  479. }
  480. }
  481. if (isset($group)) {
  482. if (isset($group[$packagetype])) {
  483. if (isset($group[$packagetype][0])) {
  484. foreach ($group[$packagetype] as $dep) {
  485. $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
  486. $group['attribs']['name'] . '"', $params);
  487. if (is_array($ret)) {
  488. $this->_downloadDeps[] = $ret;
  489. }
  490. }
  491. } else {
  492. $ret = $this->_detect2Dep($group[$packagetype], $pname,
  493. 'dependency group "' .
  494. $group['attribs']['name'] . '"', $params);
  495. if (is_array($ret)) {
  496. $this->_downloadDeps[] = $ret;
  497. }
  498. }
  499. }
  500. }
  501. }
  502. }
  503. function _detect2Dep($dep, $pname, $group, $params)
  504. {
  505. if (isset($dep['conflicts'])) {
  506. return true;
  507. }
  508. $options = $this->_downloader->getOptions();
  509. if (isset($dep['uri'])) {
  510. return array('uri' => $dep['uri'], 'dep' => $dep);;
  511. }
  512. $testdep = $dep;
  513. $testdep['package'] = $dep['name'];
  514. if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
  515. $dep['package'] = $dep['name'];
  516. if (!isset($options['soft'])) {
  517. $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
  518. ' dependency "' .
  519. $this->_registry->parsedPackageNameToString($dep, true) .
  520. '", will be installed');
  521. }
  522. return false;
  523. }
  524. $options = $this->_downloader->getOptions();
  525. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  526. if ($this->_explicitState) {
  527. $pname['state'] = $this->_explicitState;
  528. }
  529. $url =
  530. $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
  531. if (PEAR::isError($url)) {
  532. PEAR::popErrorHandling();
  533. return $url;
  534. }
  535. $dep['package'] = $dep['name'];
  536. $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
  537. !isset($options['alldeps']));
  538. PEAR::popErrorHandling();
  539. if (PEAR::isError($ret)) {
  540. if (!isset($options['soft'])) {
  541. $this->_downloader->log(0, $ret->getMessage());
  542. }
  543. return false;
  544. } else {
  545. // check to see if a dep is already installed and is the same or newer
  546. if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
  547. $oper = 'has';
  548. } else {
  549. $oper = 'gt';
  550. }
  551. // do not try to move this before getDepPackageDownloadURL
  552. // we can't determine whether upgrade is necessary until we know what
  553. // version would be downloaded
  554. if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
  555. $version = $this->_registry->packageInfo($dep['name'], 'version',
  556. $dep['channel']);
  557. $dep['package'] = $dep['name'];
  558. if (!isset($options['soft'])) {
  559. $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
  560. ' dependency "' .
  561. $this->_registry->parsedPackageNameToString($dep, true) .
  562. '" version ' . $url['version'] . ', already installed as version ' .
  563. $version);
  564. }
  565. return false;
  566. }
  567. }
  568. if (isset($dep['nodefault'])) {
  569. $ret['nodefault'] = true;
  570. }
  571. return $ret;
  572. }
  573. function _detect1($deps, $pname, $options, $params)
  574. {
  575. $this->_downloadDeps = array();
  576. $skipnames = array();
  577. foreach ($deps as $dep) {
  578. $nodownload = false;
  579. if ($dep['type'] == 'pkg') {
  580. $dep['channel'] = 'pear.php.net';
  581. $dep['package'] = $dep['name'];
  582. switch ($dep['rel']) {
  583. case 'not' :
  584. continue 2;
  585. case 'ge' :
  586. case 'eq' :
  587. case 'gt' :
  588. case 'has' :
  589. if (PEAR_Downloader_Package::willDownload($dep, $params)) {
  590. $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
  591. 'required' :
  592. 'optional';
  593. $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
  594. . ' dependency "' .
  595. $this->_registry->parsedPackageNameToString($dep, true) .
  596. '", will be installed');
  597. continue 2;
  598. }
  599. }
  600. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  601. if ($this->_explicitState) {
  602. $pname['state'] = $this->_explicitState;
  603. }
  604. $url =
  605. $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
  606. $chan = 'pear.php.net';
  607. if (PEAR::isError($url)) {
  608. // check to see if this is a pecl package that has jumped
  609. // from pear.php.net to pecl.php.net channel
  610. if (!class_exists('PEAR_Dependency2')) {
  611. require_once 'PEAR/Dependency2.php';
  612. }
  613. $newdep = PEAR_Dependency2::normalizeDep($dep);
  614. $newdep = $newdep[0];
  615. $newdep['channel'] = 'pecl.php.net';
  616. $chan = 'pecl.php.net';
  617. $url =
  618. $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
  619. if (PEAR::isError($url)) {
  620. PEAR::popErrorHandling();
  621. return $url;
  622. }
  623. }
  624. PEAR::popErrorHandling();
  625. if (!isset($options['alldeps'])) {
  626. if (isset($dep['optional']) && $dep['optional'] == 'yes') {
  627. if (!isset($options['soft'])) {
  628. $this->_downloader->log(3, 'Notice: package "' .
  629. $this->getShortName() .
  630. '" optional dependency "' .
  631. $this->_registry->parsedPackageNameToString(
  632. array('channel' => $chan, 'package' =>
  633. $dep['name']), true) .
  634. '" will not be automatically downloaded');
  635. }
  636. $skipnames[] = $this->_registry->parsedPackageNameToString(
  637. array('channel' => $chan, 'package' =>
  638. $dep['name']), true);
  639. $nodownload = true;
  640. }
  641. }
  642. if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
  643. if (!isset($dep['optional']) || $dep['optional'] == 'no') {
  644. if (!isset($options['soft'])) {
  645. $this->_downloader->log(3, 'Notice: package "' .
  646. $this->getShortName() .
  647. '" required dependency "' .
  648. $this->_registry->parsedPackageNameToString(
  649. array('channel' => $chan, 'package' =>
  650. $dep['name']), true) .
  651. '" will not be automatically downloaded');
  652. }
  653. $skipnames[] = $this->_registry->parsedPackageNameToString(
  654. array('channel' => $chan, 'package' =>
  655. $dep['name']), true);
  656. $nodownload = true;
  657. }
  658. }
  659. // check to see if a dep is already installed
  660. // do not try to move this before getDepPackageDownloadURL
  661. // we can't determine whether upgrade is necessary until we know what
  662. // version would be downloaded
  663. if (!isset($options['force']) && $this->isInstalled(
  664. $url, $dep['rel'])) {
  665. $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
  666. 'required' :
  667. 'optional';
  668. $dep['package'] = $dep['name'];
  669. if (isset($newdep)) {
  670. $version = $this->_registry->packageInfo($newdep['name'], 'version',
  671. $newdep['channel']);
  672. } else {
  673. $version = $this->_registry->packageInfo($dep['name'], 'version');
  674. }
  675. $dep['version'] = $url['version'];
  676. if (!isset($options['soft'])) {
  677. $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
  678. ' dependency "' .
  679. $this->_registry->parsedPackageNameToString($dep, true) .
  680. '", already installed as version ' . $version);
  681. }
  682. if (@$skipnames[count($skipnames) - 1] ==
  683. $this->_registry->parsedPackageNameToString($dep, true)) {
  684. array_pop($skipnames);
  685. }
  686. continue;
  687. }
  688. if ($nodownload) {
  689. continue;
  690. }
  691. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  692. if (isset($newdep)) {
  693. $dep = $newdep;
  694. }
  695. $dep['package'] = $dep['name'];
  696. $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
  697. isset($dep['optional']) && $dep['optional'] == 'yes' &&
  698. !isset($options['alldeps']));
  699. PEAR::popErrorHandling();
  700. if (PEAR::isError($ret)) {
  701. if (!isset($options['soft'])) {
  702. $this->_downloader->log(0, $ret->getMessage());
  703. }
  704. continue;
  705. }
  706. $this->_downloadDeps[] = $ret;
  707. }
  708. }
  709. if (count($skipnames)) {
  710. if (!isset($options['soft'])) {
  711. $this->_downloader->log(1, 'Did not download dependencies: ' .
  712. implode(', ', $skipnames) .
  713. ', use --alldeps or --onlyreqdeps to download automatically');
  714. }
  715. }
  716. }
  717. function setDownloadURL($pkg)
  718. {
  719. $this->_downloadURL = $pkg;
  720. }
  721. /**
  722. * Set the package.xml object for this downloaded package
  723. *
  724. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
  725. */
  726. function setPackageFile(&$pkg)
  727. {
  728. $this->_packagefile = &$pkg;
  729. }
  730. function getShortName()
  731. {
  732. return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
  733. 'package' => $this->getPackage()), true);
  734. }
  735. function getParsedPackage()
  736. {
  737. if (isset($this->_packagefile) || isset($this->_parsedname)) {
  738. return array('channel' => $this->getChannel(),
  739. 'package' => $this->getPackage(),
  740. 'version' => $this->getVersion());
  741. }
  742. return false;
  743. }
  744. function getDownloadURL()
  745. {
  746. return $this->_downloadURL;
  747. }
  748. function canDefault()
  749. {
  750. if (isset($this->_downloadURL)) {
  751. if (isset($this->_downloadURL['nodefault'])) {
  752. return false;
  753. }
  754. }
  755. return true;
  756. }
  757. function getPackage()
  758. {
  759. if (isset($this->_packagefile)) {
  760. return $this->_packagefile->getPackage();
  761. } elseif (isset($this->_downloadURL['info'])) {
  762. return $this->_downloadURL['info']->getPackage();
  763. } else {
  764. return false;
  765. }
  766. }
  767. /**
  768. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  769. */
  770. function isSubpackage(&$pf)
  771. {
  772. if (isset($this->_packagefile)) {
  773. return $this->_packagefile->isSubpackage($pf);
  774. } elseif (isset($this->_downloadURL['info'])) {
  775. return $this->_downloadURL['info']->isSubpackage($pf);
  776. } else {
  777. return false;
  778. }
  779. }
  780. function getPackageType()
  781. {
  782. if (isset($this->_packagefile)) {
  783. return $this->_packagefile->getPackageType();
  784. } elseif (isset($this->_downloadURL['info'])) {
  785. return $this->_downloadURL['info']->getPackageType();
  786. } else {
  787. return false;
  788. }
  789. }
  790. function isBundle()
  791. {
  792. if (isset($this->_packagefile)) {
  793. return $this->_packagefile->getPackageType() == 'bundle';
  794. } else {
  795. return false;
  796. }
  797. }
  798. function getPackageXmlVersion()
  799. {
  800. if (isset($this->_packagefile)) {
  801. return $this->_packagefile->getPackagexmlVersion();
  802. } elseif (isset($this->_downloadURL['info'])) {
  803. return $this->_downloadURL['info']->getPackagexmlVersion();
  804. } else {
  805. return '1.0';
  806. }
  807. }
  808. function getChannel()
  809. {
  810. if (isset($this->_packagefile)) {
  811. return $this->_packagefile->getChannel();
  812. } elseif (isset($this->_downloadURL['info'])) {
  813. return $this->_downloadURL['info']->getChannel();
  814. } else {
  815. return false;
  816. }
  817. }
  818. function getURI()
  819. {
  820. if (isset($this->_packagefile)) {
  821. return $this->_packagefile->getURI();
  822. } elseif (isset($this->_downloadURL['info'])) {
  823. return $this->_downloadURL['info']->getURI();
  824. } else {
  825. return false;
  826. }
  827. }
  828. function getVersion()
  829. {
  830. if (isset($this->_packagefile)) {
  831. return $this->_packagefile->getVersion();
  832. } elseif (isset($this->_downloadURL['version'])) {
  833. return $this->_downloadURL['version'];
  834. } else {
  835. return false;
  836. }
  837. }
  838. function isCompatible($pf)
  839. {
  840. if (isset($this->_packagefile)) {
  841. return $this->_packagefile->isCompatible($pf);
  842. } elseif (isset($this->_downloadURL['info'])) {
  843. return $this->_downloadURL['info']->isCompatible($pf);
  844. } else {
  845. return true;
  846. }
  847. }
  848. function setGroup($group)
  849. {
  850. $this->_parsedname['group'] = $group;
  851. }
  852. function getGroup()
  853. {
  854. if (isset($this->_parsedname['group'])) {
  855. return $this->_parsedname['group'];
  856. } else {
  857. return '';
  858. }
  859. }
  860. function isExtension($name)
  861. {
  862. if (isset($this->_packagefile)) {
  863. return $this->_packagefile->isExtension($name);
  864. } elseif (isset($this->_downloadURL['info'])) {
  865. return $this->_downloadURL['info']->getProvidesExtension() == $name;
  866. } else {
  867. return false;
  868. }
  869. }
  870. function getDeps()
  871. {
  872. if (isset($this->_packagefile)) {
  873. if ($this->_packagefile->getPackagexmlVersion() == '2.0') {
  874. return $this->_packagefile->getDeps(true);
  875. } else {
  876. return $this->_packagefile->getDeps();
  877. }
  878. } elseif (isset($this->_downloadURL['info'])) {
  879. if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
  880. return $this->_downloadURL['info']->getDeps(true);
  881. } else {
  882. return $this->_downloadURL['info']->getDeps();
  883. }
  884. } else {
  885. return array();
  886. }
  887. }
  888. /**
  889. * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
  890. * returned from getDepDownloadURL()
  891. */
  892. function isEqual($param)
  893. {
  894. if (is_object($param)) {
  895. $channel = $param->getChannel();
  896. $package = $param->getPackage();
  897. if ($param->getURI()) {
  898. $param = array(
  899. 'channel' => $param->getChannel(),
  900. 'package' => $param->getPackage(),
  901. 'version' => $param->getVersion(),
  902. 'uri' => $param->getURI(),
  903. );
  904. } else {
  905. $param = array(
  906. 'channel' => $param->getChannel(),
  907. 'package' => $param->getPackage(),
  908. 'version' => $param->getVersion(),
  909. );
  910. }
  911. } else {
  912. if (isset($param['uri'])) {
  913. $param['channel'] = '__uri';
  914. $param['package'] = $param['dep']['name'];
  915. }
  916. $package = isset($param['package']) ? $param['package'] :
  917. $param['info']->getPackage();
  918. $channel = isset($param['channel']) ? $param['channel'] :
  919. $param['info']->getChannel();
  920. if (isset($param['rel'])) {
  921. if (!class_exists('PEAR_Dependency2')) {
  922. require_once 'PEAR/Dependency2.php';
  923. }
  924. $newdep = PEAR_Dependency2::normalizeDep($param);
  925. $newdep = $newdep[0];
  926. } elseif (isset($param['min'])) {
  927. $newdep = $param;
  928. }
  929. }
  930. if (isset($newdep)) {
  931. if (!isset($newdep['min'])) {
  932. $newdep['min'] = '0';
  933. }
  934. if (!isset($newdep['max'])) {
  935. $newdep['max'] = '100000000000000000000';
  936. }
  937. // use magic to support pecl packages suddenly jumping to the pecl channel
  938. // we need to support both dependency possibilities
  939. if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
  940. if ($package == $this->getPackage()) {
  941. $channel = 'pecl.php.net';
  942. }
  943. }
  944. if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
  945. if ($package == $this->getPackage()) {
  946. $channel = 'pear.php.net';
  947. }
  948. }
  949. return (strtolower($package) == strtolower($this->getPackage()) &&
  950. $channel == $this->getChannel() &&
  951. version_compare($newdep['min'], $this->getVersion(), '<=') &&
  952. version_compare($newdep['max'], $this->getVersion(), '>='));
  953. }
  954. // use magic to support pecl packages suddenly jumping to the pecl channel
  955. if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
  956. if (strtolower($package) == strtolower($this->getPackage())) {
  957. $channel = 'pear.php.net';
  958. }
  959. }
  960. if (isset($param['version'])) {
  961. return (strtolower($package) == strtolower($this->getPackage()) &&
  962. $channel == $this->getChannel() &&
  963. $param['version'] == $this->getVersion());
  964. } else {
  965. return strtolower($package) == strtolower($this->getPackage()) &&
  966. $channel == $this->getChannel();
  967. }
  968. }
  969. function isInstalled($dep, $oper = '==')
  970. {
  971. if (!$dep) {
  972. return false;
  973. }
  974. if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
  975. return false;
  976. }
  977. if (is_object($dep)) {
  978. $package = $dep->getPackage();
  979. $channel = $dep->getChannel();
  980. if ($dep->getURI()) {
  981. $dep = array(
  982. 'uri' => $dep->getURI(),
  983. 'version' => $dep->getVersion(),
  984. );
  985. } else {
  986. $dep = array(
  987. 'version' => $dep->getVersion(),
  988. );
  989. }
  990. } else {
  991. if (isset($dep['uri'])) {
  992. $channel = '__uri';
  993. $package = $dep['dep']['name'];
  994. } else {
  995. $channel = $dep['info']->getChannel();
  996. $package = $dep['info']->getPackage();
  997. }
  998. }
  999. $options = $this->_downloader->getOptions();
  1000. $test = $this->_registry->packageExists($package, $channel);
  1001. if (!$test && $channel == 'pecl.php.net') {
  1002. // do magic to allow upgrading from old pecl packages to new ones
  1003. $test = $this->_registry->packageExists($package, 'pear.php.net');
  1004. $channel = 'pear.php.net';
  1005. }
  1006. if ($test) {
  1007. if (isset($dep['uri'])) {
  1008. if ($this->_registry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
  1009. return true;
  1010. }
  1011. }
  1012. if (isset($options['upgrade'])) {
  1013. if ($oper == 'has') {
  1014. if (version_compare($this->_registry->packageInfo(
  1015. $package, 'version', $channel),
  1016. $dep['version'], '>=')) {
  1017. return true;
  1018. } else {
  1019. return false;
  1020. }
  1021. } else {
  1022. if (version_compare($this->_registry->packageInfo(
  1023. $package, 'version', $channel),
  1024. $dep['version'], '>=')) {
  1025. return true;
  1026. }
  1027. return false;
  1028. }
  1029. }
  1030. return true;
  1031. }
  1032. return false;
  1033. }
  1034. /**
  1035. * @param array
  1036. * @static
  1037. */
  1038. function removeDuplicates(&$params)
  1039. {
  1040. $pnames = array();
  1041. foreach ($params as $i => $param) {
  1042. if (!$param) {
  1043. continue;
  1044. }
  1045. if ($param->getPackage()) {
  1046. $pnames[$i] = $param->getChannel() . '/' .
  1047. $param->getPackage() . '-' . $param->getVersion() . '#' . $param->getGroup();
  1048. }
  1049. }
  1050. $pnames = array_unique($pnames);
  1051. $unset = array_diff(array_keys($params), array_keys($pnames));
  1052. $testp = array_flip($pnames);
  1053. foreach ($params as $i => $param) {
  1054. if (!$param) {
  1055. $unset[] = $i;
  1056. continue;
  1057. }
  1058. if (!is_a($param, 'PEAR_Downloader_Package')) {
  1059. $unset[] = $i;
  1060. continue;
  1061. }
  1062. if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
  1063. $param->getVersion() . '#' . $param->getGroup()])) {
  1064. $unset[] = $i;
  1065. }
  1066. }
  1067. foreach ($unset as $i) {
  1068. unset($params[$i]);
  1069. }
  1070. $ret = array();
  1071. foreach ($params as $i => $param) {
  1072. $ret[] = &$params[$i];
  1073. }
  1074. $params = array();
  1075. foreach ($ret as $i => $param) {
  1076. $params[] = &$ret[$i];
  1077. }
  1078. }
  1079. function explicitState()
  1080. {
  1081. return $this->_explicitState;
  1082. }
  1083. function setExplicitState($s)
  1084. {
  1085. $this->_explicitState = $s;
  1086. }
  1087. /**
  1088. * @static
  1089. */
  1090. function mergeDependencies(&$params)
  1091. {
  1092. $newparams = array();
  1093. $bundles = array();
  1094. foreach ($params as $i => $param) {
  1095. if (!$param->isBundle()) {
  1096. continue;
  1097. }
  1098. $bundles[] = $i;
  1099. $pf = &$param->getPackageFile();
  1100. $newdeps = array();
  1101. $contents = $pf->getBundledPackages();
  1102. if (!is_array($contents)) {
  1103. $contents = array($contents);
  1104. }
  1105. foreach ($contents as $file) {
  1106. $filecontents = $pf->getFileContents($file);
  1107. $dl = &$param->getDownloader();
  1108. $options = $dl->getOptions();
  1109. $fp = @fopen($dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file, 'wb');
  1110. if (!$fp) {
  1111. continue;
  1112. }
  1113. fwrite($fp, $filecontents, strlen($filecontents));
  1114. fclose($fp);
  1115. if ($s = $params[$i]->explicitState()) {
  1116. $obj->setExplicitState($s);
  1117. }
  1118. $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
  1119. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1120. $e = $obj->_fromFile($dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file);
  1121. PEAR::popErrorHandling();
  1122. if (PEAR::isError($e)) {
  1123. if (!isset($options['soft'])) {
  1124. $dl->log(0, $e->getMessage());
  1125. }
  1126. continue;
  1127. }
  1128. $j = &$obj;
  1129. if (!PEAR_Downloader_Package::willDownload($j,
  1130. array_merge($params, $newparams)) && !$param->isInstalled($j)) {
  1131. $newparams[] = &$j;
  1132. }
  1133. }
  1134. }
  1135. foreach ($bundles as $i) {
  1136. unset($params[$i]); // remove bundles - only their contents matter for installation
  1137. }
  1138. PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
  1139. if (count($newparams)) { // add in bundled packages for install
  1140. foreach ($newparams as $i => $unused) {
  1141. $params[] = &$newparams[$i];
  1142. }
  1143. $newparams = array();
  1144. }
  1145. foreach ($params as $i => $param) {
  1146. $newdeps = array();
  1147. foreach ($param->_downloadDeps as $dep) {
  1148. if (!PEAR_Downloader_Package::willDownload($dep,
  1149. array_merge($params, $newparams)) && !$param->isInstalled($dep)) {
  1150. $newdeps[] = $dep;
  1151. } else {
  1152. // detect versioning conflicts here
  1153. }
  1154. }
  1155. // convert the dependencies into PEAR_Downloader_Package objects for the next time
  1156. // around
  1157. $params[$i]->_downloadDeps = array();
  1158. foreach ($newdeps as $dep) {
  1159. $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
  1160. if ($s = $params[$i]->explicitState()) {
  1161. $obj->setExplicitState($s);
  1162. }
  1163. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1164. $e = $obj->fromDepURL($dep);
  1165. PEAR::popErrorHandling();
  1166. if (PEAR::isError($e)) {
  1167. if (!isset($options['soft'])) {
  1168. $obj->_downloader->log(0, $e->getMessage());
  1169. }
  1170. continue;
  1171. }
  1172. $e = $obj->detectDependencies($params);
  1173. if (PEAR::isError($e)) {
  1174. if (!isset($options['soft'])) {
  1175. $obj->_downloader->log(0, $e->getMessage());
  1176. }
  1177. }
  1178. $j = &$obj;
  1179. $newparams[] = &$j;
  1180. }
  1181. }
  1182. if (count($newparams)) {
  1183. foreach ($newparams as $i => $unused) {
  1184. $params[] = &$newparams[$i];
  1185. }
  1186. return true;
  1187. } else {
  1188. return false;
  1189. }
  1190. }
  1191. /**
  1192. * @static
  1193. */
  1194. function willDownload($param, $params)
  1195. {
  1196. if (!is_array($params)) {
  1197. return false;
  1198. }
  1199. foreach ($params as $obj) {
  1200. if ($obj->isEqual($param)) {
  1201. return true;
  1202. }
  1203. }
  1204. return false;
  1205. }
  1206. /**
  1207. * For simpler unit-testing
  1208. * @param PEAR_Config
  1209. * @param int
  1210. * @param string
  1211. */
  1212. function &getPackagefileObject(&$c, $d, $t = false)
  1213. {
  1214. $a = &new PEAR_PackageFile($c, $d, $t);
  1215. return $a;
  1216. }
  1217. function _fromFile($param)
  1218. {
  1219. if (@is_file($param)) {
  1220. $this->_type = 'local';
  1221. $options = $this->_downloader->getOptions();
  1222. if (isset($options['downloadonly'])) {
  1223. $pkg = &$this->getPackagefileObject($this->_config,
  1224. $this->_downloader->_debug);
  1225. } else {
  1226. $pkg = &$this->getPackagefileObject($this->_config,
  1227. $this->_downloader->_debug, $this->_downloader->getDownloadDir());
  1228. }
  1229. PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1230. $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
  1231. PEAR::popErrorHandling();
  1232. if (PEAR::isError($pf)) {
  1233. $this->_valid = false;
  1234. return $pf;
  1235. }
  1236. $this->_packagefile = &$pf;
  1237. $this->setGroup('default'); // install the default dependency group
  1238. return $this->_valid = true;
  1239. }
  1240. return $this->_valid = false;
  1241. }
  1242. function _fromUrl($param, $saveparam = '')
  1243. {
  1244. if (!is_array($param) &&
  1245. (preg_match('#^(http|ftp)://#', $param))) {
  1246. $options = $this->_downloader->getOptions();
  1247. $this->_type = 'url';
  1248. $callback = $this->_downloader->ui ?
  1249. array(&$this->_downloader, '_downloadCallback') : null;
  1250. $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
  1251. $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
  1252. $this->_downloader->getDownloadDir(), $callback);
  1253. $this->_downloader->popErrorHandling();
  1254. if (PEAR::isError($file)) {
  1255. if (!empty($saveparam)) {
  1256. $saveparam = ", cannot download \"$saveparam\"";
  1257. }
  1258. $err = PEAR::raiseError('Could not download from "' . $param .
  1259. '"' . $saveparam);
  1260. return $err;
  1261. }
  1262. if ($this->_rawpackagefile) {
  1263. require_once 'Archive/Tar.php';
  1264. $tar = &new Archive_Tar($file);
  1265. $packagexml = $tar->extractInString('package2.xml');
  1266. if (!$packagexml) {
  1267. $packagexml = $tar->extractInString('package.xml');
  1268. }
  1269. if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
  1270. str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
  1271. if ($t

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