Bearsampp 2026.9.23
Loading...
Searching...
No Matches
PEAR_Downloader Class Reference
Inheritance diagram for PEAR_Downloader:
Collaboration diagram for PEAR_Downloader:

Public Member Functions

 __construct ($ui=null, $options=array(), $config=null)
 _checkDepTree ($channel, $package, $b, $checked=array())
 _dependsOn ($a, $b)
 _detectDepCycle (&$deplinks)
 _downloadCallback ($msg, $params=null)
 _getDepPackageDownloadUrl ($dep, $parr)
 _getPackageDownloadUrl ($parr)
 _prependPath ($path, $prepend)
 _setupGraph ($t, $reg, &$deplinks, &$nodes, $package)
 _sortInstall ($a, $b)
 _testCycle ($test, $deplinks, $dep)
 analyzeDependencies (&$params, $force=false)
 configSet ($key, $value, $layer='user', $channel=false)
 discover ($channel)
& download ($params)
& getDependency2Object (&$c, $i, $p, $s)
 getDownloadDir ()
 getDownloadedPackages ()
 getErrorMsgs ()
 getOptions ()
 getPackageDownloadUrl ($package, $version=null, $channel=false)
 newDownloaderPackage (&$t)
 pushError ($errmsg, $code=-1)
 setDownloadDir ($dir)
 setOptions ($options)
 sortPackagesForInstall (&$packages)
 sortPkgDeps (&$packages, $uninstall=false)
Public Member Functions inherited from PEAR_Common
 __construct ()
 _PEAR_Common ()
 _postProcessChecks ($pf)
 _postProcessValidPackagexml (&$pf)
 buildProvidesArray ($srcinfo)
 detectDependencies ($any, $status_callback=null)
 downloadHttp ( $url, &$ui, $save_dir='.', $callback=null, $lastmodified=null, $accept=false, $channel=false)
 infoFromAny ($info)
 infoFromDescriptionFile ($descfile)
 infoFromString ($data)
 infoFromTgzFile ($file)
 log ($level, $msg, $append_crlf=true)
 mkDirHier ($dir)
 mkTempDir ($tmpdir='')
 setFrontendObject (&$ui)
 validatePackageInfo ($info, &$errors, &$warnings, $dir_prefix='')
 validPackageName ($name)
 validPackageVersion ($ver)
 xmlFromInfo ($pkginfo)
Public Member Functions inherited from PEAR
 __call ($method, $arguments)
 __construct ($error_class=null)
 _checkDelExpect ($error_code)
 _PEAR ()
 delExpect ($error_code)
 expectError ($code=' *')
 PEAR ($error_class=null)
 popExpect ()

Static Public Member Functions

static _downloadHttp ( $object, $url, &$ui, $save_dir='.', $callback=null, $lastmodified=null, $accept=false, $channel=false)
Static Public Member Functions inherited from PEAR_Common
static addTempFile ($file)
static analyzeSourceCode ($file)
static betterStates ($state, $include=false)
static getDependencyRelations ()
static getDependencyTypes ()
static getFileRoles ()
static getProvideTypes ()
static getReleaseStates ()
static getReplacementTypes ()
static getScriptPhases ()
static getUserRoles ()
static isIncludeable ($path)
Static Public Member Functions inherited from PEAR
static __callStatic ($method, $arguments)
static getSourceDateEpoch ()
static & getStaticProperty ($class, $var)
static isError ($data, $code=null)
static loadExtension ($ext)
static registerShutdownFunc ($func, $args=array())
static staticPopErrorHandling ()
static staticPushErrorHandling ($mode, $options=null)

Data Fields

 $_downloadDir
 $_downloadedPackages = array()
 $_errorStack = array()
 $_installed = array()
 $_internalDownload = false
 $_options
 $_packageSortTree
 $_preferredState
 $_registry
 $_toDownload = array()
Data Fields inherited from PEAR_Common
 $_validPackageFile
 $config = null
 $current_attributes = array()
 $current_element
 $current_path = null
 $element_stack = array()
 $pkginfo = array()
 $ui = null
Data Fields inherited from PEAR
 $_debug = false
 $_default_error_handler = ''
 $_default_error_mode = null
 $_default_error_options = null
 $_error_class = 'PEAR_Error'
 $_expected_errors = array()

Static Protected Attributes

static $bivalentMethods
Static Protected Attributes inherited from PEAR
static $bivalentMethods

Additional Inherited Members

Static Protected Member Functions inherited from PEAR
static _popErrorHandling ($object)
static _pushErrorHandling ($object, $mode, $options=null)
static _raiseError ($object, $message=null, $code=null, $mode=null, $options=null, $userinfo=null, $error_class=null, $skipmsg=false)
static _setErrorHandling ( $object, $mode=null, $options=null)
static _throwError ($object, $message=null, $code=null, $userinfo=null)

Detailed Description

Definition at line 46 of file Downloader.php.

Constructor & Destructor Documentation

◆ __construct()

__construct ( $ui = null,
$options = array(),
$config = null )
Parameters
PEAR_Frontend_*
array
PEAR_Config

Definition at line 162 of file Downloader.php.

163 {
164 parent::__construct();
165 $this->_options = $options;
166 if ($config !== null) {
167 $this->config = &$config;
168 $this->_preferredState = $this->config->get('preferred_state');
169 }
170 $this->ui = &$ui;
171 if (!$this->_preferredState) {
172 // don't inadvertently use a non-set preferred_state
173 $this->_preferredState = null;
174 }
175
176 if ($config !== null) {
177 if (isset($this->_options['installroot'])) {
178 $this->config->setInstallRoot($this->_options['installroot']);
179 }
180 $this->_registry = &$config->getRegistry();
181 }
182
183 if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
184 $this->_installed = $this->_registry->listAllPackages();
185 foreach ($this->_installed as $key => $unused) {
186 if (!count($unused)) {
187 continue;
188 }
189 $strtolower = function($a) { return strtolower($a); };
190 array_walk($this->_installed[$key], $strtolower);
191 }
192 }
193 }
$options
Definition pearcmd.php:145

References PEAR_Common\$config, $options, and PEAR_Common\$ui.

Member Function Documentation

◆ _checkDepTree()

_checkDepTree ( $channel,
$package,
$b,
$checked = array() )

Definition at line 1464 of file Downloader.php.

1465 {
1466 $checked[$channel][$package] = true;
1467 if (!isset($this->_depTree[$channel][$package])) {
1468 return false;
1469 }
1470
1471 if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
1472 [strtolower($b->getPackage())])) {
1473 return true;
1474 }
1475
1476 foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
1477 foreach ($packages as $pa => $true) {
1478 if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
1479 return true;
1480 }
1481 }
1482 }
1483
1484 return false;
1485 }
_checkDepTree($channel, $package, $b, $checked=array())

References _checkDepTree().

Referenced by _checkDepTree(), and _dependsOn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _dependsOn()

_dependsOn ( $a,
$b )

Definition at line 1459 of file Downloader.php.

1460 {
1461 return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
1462 }

References _checkDepTree().

Referenced by _sortInstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _detectDepCycle()

_detectDepCycle ( & $deplinks)

Detect recursive links between dependencies and break the cycles

Parameters
array@access private

Definition at line 1374 of file Downloader.php.

1375 {
1376 do {
1377 $keepgoing = false;
1378 foreach ($deplinks as $dep => $parents) {
1379 foreach ($parents as $parent => $unused) {
1380 // reset the parent cycle detector
1381 $this->_testCycle(null, null, null);
1382 if ($this->_testCycle($dep, $deplinks, $parent)) {
1383 $keepgoing = true;
1384 unset($deplinks[$dep][$parent]);
1385 if (count($deplinks[$dep]) == 0) {
1386 unset($deplinks[$dep]);
1387 }
1388
1389 continue 3;
1390 }
1391 }
1392 }
1393 } while ($keepgoing);
1394 }
_testCycle($test, $deplinks, $dep)

References _testCycle().

Referenced by sortPackagesForInstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _downloadCallback()

_downloadCallback ( $msg,
$params = null )

Definition at line 1122 of file Downloader.php.

1123 {
1124 switch ($msg) {
1125 case 'saveas':
1126 $this->log(1, "downloading $params ...");
1127 break;
1128 case 'done':
1129 $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
1130 break;
1131 case 'bytesread':
1132 static $bytes;
1133 if (empty($bytes)) {
1134 $bytes = 0;
1135 }
1136 if (!($bytes % 10240)) {
1137 $this->log(1, '.', false);
1138 }
1139 $bytes += $params;
1140 break;
1141 case 'start':
1142 if($params[1] == -1) {
1143 $length = "Unknown size";
1144 } else {
1145 $length = number_format($params[1], 0, '', ',')." bytes";
1146 }
1147 $this->log(1, "Starting to download {$params[0]} ($length)");
1148 break;
1149 }
1150 if (method_exists($this->ui, '_downloadCallback'))
1151 $this->ui->_downloadCallback($msg, $params);
1152 }
log($level, $msg, $append_crlf=true)
Definition Common.php:244

References PEAR_Common\log().

Here is the call graph for this function:

◆ _downloadHttp()

_downloadHttp ( $object,
$url,
& $ui,
$save_dir = '.',
$callback = null,
$lastmodified = null,
$accept = false,
$channel = false )
static

Download a file through HTTP. Considers suggested file name in Content-disposition: header and can run a callback function for different events. The callback will be called with two parameters: the callback type, and parameters. The implemented callback types are:

'setup' called at the very beginning, parameter is a UI object that should be used for all output 'message' the parameter is a string with an informational message 'saveas' may be used to save with a different file name, the parameter is the filename that is about to be used. If a 'saveas' callback returns a non-empty string, that file name will be used as the filename instead. Note that $save_dir will not be affected by this, only the basename of the file. 'start' download is starting, parameter is number of bytes that are expected, or -1 if unknown 'bytesread' parameter is the number of bytes read so far 'done' download is complete, parameter is the total number of bytes read 'connfailed' if the TCP/SSL connection fails, this callback is called with array(host,port,errno,errmsg) 'writefailed' if writing to disk fails, this callback is called with array(destfile,errmsg)

If an HTTP proxy has been configured (http_proxy PEAR_Config setting), the proxy will be used.

Parameters
string$urlthe URL to download
object$uiPEAR_Frontend_* instance
object$configPEAR_Config instance
string$save_dirdirectory to save file in
mixed$callbackfunction/method to call for status updates
false | string | array$lastmodifiedheader values to check against for caching use false to return the header values from this download
false | array$acceptAccept headers to send
false | string$channelChannel to use for retrieving authentication
Returns
mixed Returns the full path of the downloaded file or a PEAR error on failure. If the error is caused by socket-related errors, the error object will have the fsockopen error code available through getCode(). If caching is requested, then return the header values. If $lastmodified was given and the there are no changes, boolean false is returned.

@access public

Definition at line 1558 of file Downloader.php.

1561 {
1562 static $redirect = 0;
1563 // always reset , so we are clean case of error
1564 $wasredirect = $redirect;
1565 $redirect = 0;
1566 if ($callback) {
1567 call_user_func($callback, 'setup', array(&$ui));
1568 }
1569
1570 $info = parse_url($url);
1571 if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
1572 return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
1573 }
1574
1575 if (!isset($info['host'])) {
1576 return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
1577 }
1578
1579 $host = isset($info['host']) ? $info['host'] : null;
1580 $port = isset($info['port']) ? $info['port'] : null;
1581 $path = isset($info['path']) ? $info['path'] : null;
1582
1583 if ($object !== null) {
1584 $config = $object->config;
1585 } else {
1586 $config = &PEAR_Config::singleton();
1587 }
1588
1589 $proxy = new PEAR_Proxy($config);
1590
1591 if ($proxy->isProxyConfigured() && $callback) {
1592 call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
1593 }
1594
1595 if (empty($port)) {
1596 $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
1597 }
1598
1599 $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
1600 $secure = ($scheme == 'https');
1601
1602 $fp = $proxy->openSocket($host, $port, $secure);
1603 if (PEAR::isError($fp)) {
1604 if ($callback) {
1605 $errno = $fp->getCode();
1606 $errstr = $fp->getMessage();
1607 call_user_func($callback, 'connfailed', array($host, $port,
1608 $errno, $errstr));
1609 }
1610 return $fp;
1611 }
1612
1613 $requestPath = $path;
1614 if ($proxy->isProxyConfigured()) {
1615 $requestPath = $url;
1616 }
1617
1618 if ($lastmodified === false || $lastmodified) {
1619 $request = "GET $requestPath HTTP/1.1\r\n";
1620 } else {
1621 $request = "GET $requestPath HTTP/1.0\r\n";
1622 }
1623 $request .= "Host: $host\r\n";
1624
1625 $ifmodifiedsince = '';
1626 if (is_array($lastmodified)) {
1627 if (isset($lastmodified['Last-Modified'])) {
1628 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
1629 }
1630
1631 if (isset($lastmodified['ETag'])) {
1632 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
1633 }
1634 } else {
1635 $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
1636 }
1637
1638 $request .= $ifmodifiedsince .
1639 "User-Agent: PEAR/1.10.18/PHP/" . PHP_VERSION . "\r\n";
1640
1641 if ($object !== null) { // only pass in authentication for non-static calls
1642 $username = $config->get('username', null, $channel);
1643 $password = $config->get('password', null, $channel);
1644 if ($username && $password) {
1645 $tmp = base64_encode("$username:$password");
1646 $request .= "Authorization: Basic $tmp\r\n";
1647 }
1648 }
1649
1650 $proxyAuth = $proxy->getProxyAuth();
1651 if ($proxyAuth) {
1652 $request .= 'Proxy-Authorization: Basic ' .
1653 $proxyAuth . "\r\n";
1654 }
1655
1656 if ($accept) {
1657 $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
1658 }
1659
1660 $request .= "Connection: close\r\n";
1661 $request .= "\r\n";
1662 fwrite($fp, $request);
1663 $headers = array();
1664 $reply = 0;
1665 while (trim($line = fgets($fp, 1024))) {
1666 if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
1667 $headers[strtolower($matches[1])] = trim($matches[2]);
1668 } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
1669 $reply = (int)$matches[1];
1670 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
1671 return false;
1672 }
1673
1674 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
1675 return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
1676 }
1677 }
1678 }
1679
1680 if ($reply != 200) {
1681 if (!isset($headers['location'])) {
1682 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
1683 }
1684
1685 if ($wasredirect > 4) {
1686 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
1687 }
1688
1689 $redirect = $wasredirect + 1;
1690 return static::_downloadHttp($object, $headers['location'],
1691 $ui, $save_dir, $callback, $lastmodified, $accept);
1692 }
1693
1694 if (isset($headers['content-disposition']) &&
1695 preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
1696 $save_as = basename($matches[1]);
1697 } else {
1698 $save_as = basename($url);
1699 }
1700
1701 if ($callback) {
1702 $tmp = call_user_func($callback, 'saveas', $save_as);
1703 if ($tmp) {
1704 $save_as = $tmp;
1705 }
1706 }
1707
1708 $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
1709 if (is_link($dest_file)) {
1710 return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
1711 }
1712
1713 if (!$wp = @fopen($dest_file, 'wb')) {
1714 fclose($fp);
1715 if ($callback) {
1716 call_user_func($callback, 'writefailed',
1717 array($dest_file, error_get_last()["message"]));
1718 }
1719 return PEAR::raiseError("could not open $dest_file for writing");
1720 }
1721
1722 $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
1723
1724 $bytes = 0;
1725 if ($callback) {
1726 call_user_func($callback, 'start', array(basename($dest_file), $length));
1727 }
1728
1729 if (isset($headers['transfer-encoding']) && strtolower($headers['transfer-encoding']) === 'chunked') {
1730 while (!feof($fp)) {
1731 $chunk_size = hexdec(fgets($fp));
1732 if ($chunk_size === 0) {
1733 break;
1734 }
1735 $data = fread($fp, $chunk_size);
1736 $bytes += strlen($data);
1737 if ($callback) {
1738 call_user_func($callback, 'bytesread', $bytes);
1739 }
1740 if (!@fwrite($wp, $data)) {
1741 fclose($fp);
1742 if ($callback) {
1743 call_user_func($callback, 'writefailed',
1744 array($dest_file, error_get_last()["message"]));
1745 }
1746 return PEAR::raiseError(
1747 "$dest_file: write failed (" . error_get_last()["message"] . ")");
1748 }
1749 fgets($fp); // Skip the trailing CRLF
1750 }
1751 } else {
1752 while ($data = fread($fp, 1024)) {
1753 $bytes += strlen($data);
1754 if ($callback) {
1755 call_user_func($callback, 'bytesread', $bytes);
1756 }
1757 if (!@fwrite($wp, $data)) {
1758 fclose($fp);
1759 if ($callback) {
1760 call_user_func($callback, 'writefailed',
1761 array($dest_file, error_get_last()["message"]));
1762 }
1763 return PEAR::raiseError(
1764 "$dest_file: write failed (" . error_get_last()["message"] . ")");
1765 }
1766 }
1767 }
1768
1769 fclose($fp);
1770 fclose($wp);
1771 if ($callback) {
1772 call_user_func($callback, 'done', $bytes);
1773 }
1774
1775 if ($lastmodified === false || $lastmodified) {
1776 if (isset($headers['etag'])) {
1777 $lastmodified = array('ETag' => $headers['etag']);
1778 }
1779
1780 if (isset($headers['last-modified'])) {
1781 if (is_array($lastmodified)) {
1782 $lastmodified['Last-Modified'] = $headers['last-modified'];
1783 } else {
1784 $lastmodified = $headers['last-modified'];
1785 }
1786 }
1787 return array($dest_file, $lastmodified, $headers);
1788 }
1789 return $dest_file;
1790 }
$port

References PEAR_Common\$config, $port, PEAR_Common\$ui, and PEAR\isError().

Referenced by PEAR_Common\downloadHttp().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _getDepPackageDownloadUrl()

_getDepPackageDownloadUrl ( $dep,
$parr )
Parameters
arraydependency array @access private

Definition at line 947 of file Downloader.php.

948 {
949 $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
950 $curchannel = $this->config->get('default_channel');
951 if (isset($dep['uri'])) {
952 $xsdversion = '2.0';
953 $chan = $this->_registry->getChannel('__uri');
954 if (PEAR::isError($chan)) {
955 return $chan;
956 }
957
958 $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
959 $this->configSet('default_channel', '__uri');
960 } else {
961 if (isset($dep['channel'])) {
962 $remotechannel = $dep['channel'];
963 } else {
964 $remotechannel = 'pear.php.net';
965 }
966
967 if (!$this->_registry->channelExists($remotechannel)) {
968 do {
969 if ($this->config->get('auto_discover')) {
970 if ($this->discover($remotechannel)) {
971 break;
972 }
973 }
974 return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
975 } while (false);
976 }
977
978 $chan = $this->_registry->getChannel($remotechannel);
979 if (PEAR::isError($chan)) {
980 return $chan;
981 }
982
983 $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
984 $this->configSet('default_channel', $remotechannel);
985 }
986
987 $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
988 if (isset($parr['state']) && isset($parr['version'])) {
989 unset($parr['state']);
990 }
991
992 if (isset($dep['uri'])) {
993 $info = $this->newDownloaderPackage($this);
995 $err = $info->initialize($dep);
997 if (!$err) {
998 // skip parameters that were missed by preferred_state
999 return PEAR::raiseError('Cannot initialize dependency');
1000 }
1001
1002 if (PEAR::isError($err)) {
1003 if (!isset($this->_options['soft'])) {
1004 $this->log(0, $err->getMessage());
1005 }
1006
1007 if (is_object($info)) {
1008 $param = $info->getChannel() . '/' . $info->getPackage();
1009 }
1010 return PEAR::raiseError('Package "' . $param . '" is not valid');
1011 }
1012 return $info;
1013 } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
1014 &&
1015 (
1016 ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
1017 ||
1018 ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
1019 )
1020 ) {
1021 if ($base2) {
1022 $base = $base2;
1023 $rest = &$this->config->getREST('1.3', $this->_options);
1024 } else {
1025 $rest = &$this->config->getREST('1.0', $this->_options);
1026 }
1027
1028 $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
1029 $state, $version, $chan->getName());
1030 if (PEAR::isError($url)) {
1031 return $url;
1032 }
1033
1034 if ($parr['channel'] != $curchannel) {
1035 $this->configSet('default_channel', $curchannel);
1036 }
1037
1038 if (!is_array($url)) {
1039 return $url;
1040 }
1041
1042 $url['raw'] = false; // no checking is necessary for REST
1043 if (!is_array($url['info'])) {
1044 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
1045 'this should never happen');
1046 }
1047
1048 if (isset($url['info']['required'])) {
1049 if (!class_exists('PEAR_PackageFile_v2')) {
1050 require_once 'PEAR/PackageFile/v2.php';
1051 }
1052 $pf = new PEAR_PackageFile_v2;
1053 $pf->setRawChannel($remotechannel);
1054 } else {
1055 if (!class_exists('PEAR_PackageFile_v1')) {
1056 require_once 'PEAR/PackageFile/v1.php';
1057 }
1058 $pf = new PEAR_PackageFile_v1;
1059
1060 }
1061 $pf->setRawPackage($url['package']);
1062 $pf->setDeps($url['info']);
1063 if ($url['compatible']) {
1064 $pf->setCompatible($url['compatible']);
1065 }
1066
1067 $pf->setRawState($url['stability']);
1068 $url['info'] = &$pf;
1069 if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
1070 $ext = '.tar';
1071 } else {
1072 $ext = '.tgz';
1073 }
1074
1075 if (is_array($url) && isset($url['url'])) {
1076 $url['url'] .= $ext;
1077 }
1078
1079 return $url;
1080 }
1081
1082 return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
1083 }
const PEAR_ERROR_RETURN
Definition PEAR.php:24
discover($channel)
configSet($key, $value, $layer='user', $channel=false)
newDownloaderPackage(&$t)
static staticPopErrorHandling()
Definition PEAR.php:654
static staticPushErrorHandling($mode, $options=null)
Definition PEAR.php:619

References configSet(), discover(), PEAR\isError(), PEAR_Common\log(), newDownloaderPackage(), PEAR_ERROR_RETURN, PEAR_PackageFile_v2\setRawChannel(), PEAR\staticPopErrorHandling(), and PEAR\staticPushErrorHandling().

Here is the call graph for this function:

◆ _getPackageDownloadUrl()

_getPackageDownloadUrl ( $parr)
Parameters
arrayoutput of parsePackageName() @access private

Definition at line 811 of file Downloader.php.

812 {
813 $curchannel = $this->config->get('default_channel');
814 $this->configSet('default_channel', $parr['channel']);
815 // getDownloadURL returns an array. On error, it only contains information
816 // on the latest release as array(version, info). On success it contains
817 // array(version, info, download url string)
818 $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
819 if (!$this->_registry->channelExists($parr['channel'])) {
820 do {
821 if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
822 break;
823 }
824
825 $this->configSet('default_channel', $curchannel);
826 return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
827 } while (false);
828 }
829
830 $chan = $this->_registry->getChannel($parr['channel']);
831 if (PEAR::isError($chan)) {
832 return $chan;
833 }
834
836 $version = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
837 $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
838 // package is installed - use the installed release stability level
839 if (!isset($parr['state']) && $stability !== null) {
840 $state = $stability['release'];
841 }
843 $base2 = false;
844
845 $preferred_mirror = $this->config->get('preferred_mirror');
846 if (!$chan->supportsREST($preferred_mirror) ||
847 (
848 !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
849 &&
850 !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
851 )
852 ) {
853 return $this->raiseError($parr['channel'] . ' is using an unsupported protocol - This should never happen. Use --force to continue');
854 }
855
856 if ($base2) {
857 $rest = &$this->config->getREST('1.3', $this->_options);
858 $base = $base2;
859 } else {
860 $rest = &$this->config->getREST('1.0', $this->_options);
861 }
862
863 $downloadVersion = false;
864 if (!isset($parr['version']) && !isset($parr['state']) && $version
865 && !PEAR::isError($version)
866 && !isset($this->_options['downloadonly'])
867 ) {
868 $downloadVersion = $version;
869 }
870
871 $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
872 if (PEAR::isError($url)) {
873 $this->configSet('default_channel', $curchannel);
874 return $url;
875 }
876
877 if ($parr['channel'] != $curchannel) {
878 $this->configSet('default_channel', $curchannel);
879 }
880
881 if (!is_array($url)) {
882 return $url;
883 }
884
885 $url['raw'] = false; // no checking is necessary for REST
886 if (!is_array($url['info'])) {
887 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
888 'this should never happen');
889 }
890
891 if (!isset($this->_options['force']) &&
892 !isset($this->_options['downloadonly']) &&
893 $version &&
894 !PEAR::isError($version) &&
895 !isset($parr['group'])
896 ) {
897 if (version_compare($version, $url['version'], '=')) {
898 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
899 $parr, true) . ' is already installed and is the same as the ' .
900 'released version ' . $url['version'], -976);
901 }
902
903 if (version_compare($version, $url['version'], '>')) {
904 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
905 $parr, true) . ' is already installed and is newer than detected ' .
906 'released version ' . $url['version'], -976);
907 }
908 }
909
910 if (isset($url['info']['required']) || $url['compatible']) {
911 require_once 'PEAR/PackageFile/v2.php';
912 $pf = new PEAR_PackageFile_v2;
913 $pf->setRawChannel($parr['channel']);
914 if ($url['compatible']) {
915 $pf->setRawCompatible($url['compatible']);
916 }
917 } else {
918 require_once 'PEAR/PackageFile/v1.php';
919 $pf = new PEAR_PackageFile_v1;
920 }
921
922 $pf->setRawPackage($url['package']);
923 $pf->setDeps($url['info']);
924 if ($url['compatible']) {
925 $pf->setCompatible($url['compatible']);
926 }
927
928 $pf->setRawState($url['stability']);
929 $url['info'] = &$pf;
930 if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
931 $ext = '.tar';
932 } else {
933 $ext = '.tgz';
934 }
935
936 if (is_array($url) && isset($url['url'])) {
937 $url['url'] .= $ext;
938 }
939
940 return $url;
941 }

References configSet(), PEAR\isError(), PEAR_ERROR_RETURN, PEAR_PackageFile_v2\setRawChannel(), PEAR\staticPopErrorHandling(), and PEAR\staticPushErrorHandling().

Here is the call graph for this function:

◆ _prependPath()

_prependPath ( $path,
$prepend )

Definition at line 1154 of file Downloader.php.

1155 {
1156 if (strlen($prepend) > 0) {
1157 if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
1158 if (preg_match('/^[a-z]:/i', $prepend)) {
1159 $prepend = substr($prepend, 2);
1160 } elseif ($prepend[0] != '\\') {
1161 $prepend = "\\$prepend";
1162 }
1163 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
1164 } else {
1165 $path = $prepend . $path;
1166 }
1167 }
1168 return $path;
1169 }

Referenced by PEAR_Installer\_compileSourceFiles(), PEAR_Installer\_installFile(), PEAR_Installer\_installFile2(), PEAR_Installer\commitFileTransaction(), download(), and PEAR_Installer\install().

Here is the caller graph for this function:

◆ _setupGraph()

_setupGraph ( $t,
$reg,
& $deplinks,
& $nodes,
$package )

Set up the dependency for installation parsing

Parameters
array$tdependency information
PEAR_Registry$reg
array$deplinkslist of dependency links already established
array$nodesall existing package nodes
string$packageparent package name @access private

Definition at line 1440 of file Downloader.php.

1441 {
1442 foreach ($t as $dep) {
1443 $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
1444 $dname = $reg->parsedPackageNameToString(
1445 array(
1446 'channel' => $depchannel,
1447 'package' => strtolower($dep['name']),
1448 ));
1449
1450 if (isset($nodes[$dname])) {
1451 if (!isset($deplinks[$dname])) {
1452 $deplinks[$dname] = array();
1453 }
1454 $deplinks[$dname][$package] = 1;
1455 }
1456 }
1457 }

Referenced by sortPackagesForInstall().

Here is the caller graph for this function:

◆ _sortInstall()

_sortInstall ( $a,
$b )

Definition at line 1487 of file Downloader.php.

1488 {
1489 if (!$a->getDeps() && !$b->getDeps()) {
1490 return 0; // neither package has dependencies, order is insignificant
1491 }
1492 if ($a->getDeps() && !$b->getDeps()) {
1493 return 1; // $a must be installed after $b because $a has dependencies
1494 }
1495 if (!$a->getDeps() && $b->getDeps()) {
1496 return -1; // $b must be installed after $a because $b has dependencies
1497 }
1498 // both packages have dependencies
1499 if ($this->_dependsOn($a, $b)) {
1500 return 1;
1501 }
1502 if ($this->_dependsOn($b, $a)) {
1503 return -1;
1504 }
1505 return 0;
1506 }

References _dependsOn().

Here is the call graph for this function:

◆ _testCycle()

_testCycle ( $test,
$deplinks,
$dep )

Definition at line 1396 of file Downloader.php.

1397 {
1398 static $visited = array();
1399 if ($test === null) {
1400 $visited = array();
1401 return;
1402 }
1403
1404 // this happens when a parent has a dep cycle on another dependency
1405 // but the child is not part of the cycle
1406 if (isset($visited[$dep])) {
1407 return false;
1408 }
1409
1410 $visited[$dep] = 1;
1411 if ($test == $dep) {
1412 return true;
1413 }
1414
1415 if (isset($deplinks[$dep])) {
1416 if (in_array($test, array_keys($deplinks[$dep]), true)) {
1417 return true;
1418 }
1419
1420 foreach ($deplinks[$dep] as $parent => $unused) {
1421 if ($this->_testCycle($test, $deplinks, $parent)) {
1422 return true;
1423 }
1424 }
1425 }
1426
1427 return false;
1428 }

References _testCycle().

Referenced by _detectDepCycle(), and _testCycle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ analyzeDependencies()

analyzeDependencies ( & $params,
$force = false )
Parameters
arrayall packages to be installed

Definition at line 516 of file Downloader.php.

517 {
518 if (isset($this->_options['downloadonly'])) {
519 return;
520 }
521
523 $redo = true;
524 $reset = $hasfailed = $failed = false;
525 while ($redo) {
526 $redo = false;
527 foreach ($params as $i => $param) {
528 $deps = $param->getDeps();
529 if (!$deps) {
530 $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
531 $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
532 $send = $param->getPackageFile();
533
534 $installcheck = $depchecker->validatePackage($send, $this, $params);
535 if (PEAR::isError($installcheck)) {
536 if (!isset($this->_options['soft'])) {
537 $this->log(0, $installcheck->getMessage());
538 }
539 $hasfailed = true;
540 $params[$i] = false;
541 $reset = true;
542 $redo = true;
543 $failed = false;
545 continue 2;
546 }
547 continue;
548 }
549
550 if (!$reset && $param->alreadyValidated() && !$force) {
551 continue;
552 }
553
554 if (count($deps)) {
555 $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
556 $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
557 $send = $param->getPackageFile();
558 if ($send === null) {
559 $send = $param->getDownloadURL();
560 }
561
562 $installcheck = $depchecker->validatePackage($send, $this, $params);
563 if (PEAR::isError($installcheck)) {
564 if (!isset($this->_options['soft'])) {
565 $this->log(0, $installcheck->getMessage());
566 }
567 $hasfailed = true;
568 $params[$i] = false;
569 $reset = true;
570 $redo = true;
571 $failed = false;
573 continue 2;
574 }
575
576 $failed = false;
577 if (isset($deps['required']) && is_array($deps['required'])) {
578 foreach ($deps['required'] as $type => $dep) {
579 // note: Dependency2 will never return a PEAR_Error if ignore-errors
580 // is specified, so soft is needed to turn off logging
581 if (!isset($dep[0])) {
582 if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
583 true, $params))) {
584 $failed = true;
585 if (!isset($this->_options['soft'])) {
586 $this->log(0, $e->getMessage());
587 }
588 } elseif (is_array($e) && !$param->alreadyValidated()) {
589 if (!isset($this->_options['soft'])) {
590 $this->log(0, $e[0]);
591 }
592 }
593 } else {
594 foreach ($dep as $d) {
595 if (PEAR::isError($e =
596 $depchecker->{"validate{$type}Dependency"}($d,
597 true, $params))) {
598 $failed = true;
599 if (!isset($this->_options['soft'])) {
600 $this->log(0, $e->getMessage());
601 }
602 } elseif (is_array($e) && !$param->alreadyValidated()) {
603 if (!isset($this->_options['soft'])) {
604 $this->log(0, $e[0]);
605 }
606 }
607 }
608 }
609 }
610
611 if (isset($deps['optional']) && is_array($deps['optional'])) {
612 foreach ($deps['optional'] as $type => $dep) {
613 if (!isset($dep[0])) {
614 if (PEAR::isError($e =
615 $depchecker->{"validate{$type}Dependency"}($dep,
616 false, $params))) {
617 $failed = true;
618 if (!isset($this->_options['soft'])) {
619 $this->log(0, $e->getMessage());
620 }
621 } elseif (is_array($e) && !$param->alreadyValidated()) {
622 if (!isset($this->_options['soft'])) {
623 $this->log(0, $e[0]);
624 }
625 }
626 } else {
627 foreach ($dep as $d) {
628 if (PEAR::isError($e =
629 $depchecker->{"validate{$type}Dependency"}($d,
630 false, $params))) {
631 $failed = true;
632 if (!isset($this->_options['soft'])) {
633 $this->log(0, $e->getMessage());
634 }
635 } elseif (is_array($e) && !$param->alreadyValidated()) {
636 if (!isset($this->_options['soft'])) {
637 $this->log(0, $e[0]);
638 }
639 }
640 }
641 }
642 }
643 }
644
645 $groupname = $param->getGroup();
646 if (isset($deps['group']) && $groupname) {
647 if (!isset($deps['group'][0])) {
648 $deps['group'] = array($deps['group']);
649 }
650
651 $found = false;
652 foreach ($deps['group'] as $group) {
653 if ($group['attribs']['name'] == $groupname) {
654 $found = true;
655 break;
656 }
657 }
658
659 if ($found) {
660 unset($group['attribs']);
661 foreach ($group as $type => $dep) {
662 if (!isset($dep[0])) {
663 if (PEAR::isError($e =
664 $depchecker->{"validate{$type}Dependency"}($dep,
665 false, $params))) {
666 $failed = true;
667 if (!isset($this->_options['soft'])) {
668 $this->log(0, $e->getMessage());
669 }
670 } elseif (is_array($e) && !$param->alreadyValidated()) {
671 if (!isset($this->_options['soft'])) {
672 $this->log(0, $e[0]);
673 }
674 }
675 } else {
676 foreach ($dep as $d) {
677 if (PEAR::isError($e =
678 $depchecker->{"validate{$type}Dependency"}($d,
679 false, $params))) {
680 $failed = true;
681 if (!isset($this->_options['soft'])) {
682 $this->log(0, $e->getMessage());
683 }
684 } elseif (is_array($e) && !$param->alreadyValidated()) {
685 if (!isset($this->_options['soft'])) {
686 $this->log(0, $e[0]);
687 }
688 }
689 }
690 }
691 }
692 }
693 }
694 } else {
695 foreach ($deps as $dep) {
696 if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
697 $failed = true;
698 if (!isset($this->_options['soft'])) {
699 $this->log(0, $e->getMessage());
700 }
701 } elseif (is_array($e) && !$param->alreadyValidated()) {
702 if (!isset($this->_options['soft'])) {
703 $this->log(0, $e[0]);
704 }
705 }
706 }
707 }
708 $params[$i]->setValidated();
709 }
710
711 if ($failed) {
712 $hasfailed = true;
713 $params[$i] = false;
714 $reset = true;
715 $redo = true;
716 $failed = false;
718 continue 2;
719 }
720 }
721 }
722
724 if ($hasfailed && (isset($this->_options['ignore-errors']) ||
725 isset($this->_options['nodeps']))) {
726 // this is probably not needed, but just in case
727 if (!isset($this->_options['soft'])) {
728 $this->log(0, 'WARNING: dependencies failed');
729 }
730 }
731 }
const PEAR_VALIDATE_DOWNLOADING
Definition Validate.php:21
static removeDuplicates(&$params, $ignoreGroups=false)
Definition Package.php:1283
& getDependency2Object(&$c, $i, $p, $s)

References getDependency2Object(), getOptions(), PEAR\isError(), PEAR_Common\log(), PEAR_ERROR_RETURN, PEAR_VALIDATE_DOWNLOADING, PEAR_Downloader_Package\removeDuplicates(), and PEAR\staticPushErrorHandling().

Referenced by download(), and PEAR_Installer\setDownloadedPackages().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ configSet()

configSet ( $key,
$value,
$layer = 'user',
$channel = false )

Definition at line 786 of file Downloader.php.

787 {
788 $this->config->set($key, $value, $layer, $channel);
789 $this->_preferredState = $this->config->get('preferred_state', null, $channel);
790 if (!$this->_preferredState) {
791 // don't inadvertently use a non-set preferred_state
792 $this->_preferredState = null;
793 }
794 }

Referenced by PEAR_Installer\_compileSourceFiles(), _getDepPackageDownloadUrl(), _getPackageDownloadUrl(), PEAR_Installer\install(), and PEAR_Installer\uninstall().

Here is the caller graph for this function:

◆ discover()

discover ( $channel)

Attempt to discover a channel's remote capabilities from its server name

Parameters
string
Returns
boolean

Definition at line 201 of file Downloader.php.

202 {
203 $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
204 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
205 $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
206 if (!class_exists('System')) {
207 require_once 'System.php';
208 }
209
210 $tmpdir = $this->config->get('temp_dir');
211 $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
212 $a = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
213 PEAR::popErrorHandling();
214 if (PEAR::isError($a)) {
215 // Attempt to fallback to https automatically.
216 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
217 $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
218 $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
219 PEAR::popErrorHandling();
220 if (PEAR::isError($a)) {
221 return false;
222 }
223 }
224
225 list($a, $lastmodified) = $a;
226 if (!class_exists('PEAR_ChannelFile')) {
227 require_once 'PEAR/ChannelFile.php';
228 }
229
230 $b = new PEAR_ChannelFile;
231 if ($b->fromXmlFile($a)) {
232 unlink($a);
233 if ($this->config->get('auto_discover')) {
234 $this->_registry->addChannel($b, $lastmodified);
235 $alias = $b->getName();
236 if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
237 $alias = $b->getAlias();
238 }
239
240 $this->log(1, 'Auto-discovered channel "' . $channel .
241 '", alias "' . $alias . '", adding to registry');
242 }
243
244 return true;
245 }
246
247 unlink($a);
248 return false;
249 }
downloadHttp( $url, &$ui, $save_dir='.', $callback=null, $lastmodified=null, $accept=false, $channel=false)
Definition Common.php:823
static mktemp($args=null)
Definition System.php:395

References PEAR_Common\downloadHttp(), PEAR\isError(), PEAR_Common\log(), and PEAR_ERROR_RETURN.

Referenced by _getDepPackageDownloadUrl().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ download()

& download ( $params)

Definition at line 281 of file Downloader.php.

282 {
283 if (!count($params)) {
284 $a = array();
285 return $a;
286 }
287
288 if (!isset($this->_registry)) {
289 $this->_registry = &$this->config->getRegistry();
290 }
291
292 $channelschecked = array();
293 // convert all parameters into PEAR_Downloader_Package objects
294 foreach ($params as $i => $param) {
295 $params[$i] = $this->newDownloaderPackage($this);
297 $err = $params[$i]->initialize($param);
299 if (!$err) {
300 // skip parameters that were missed by preferred_state
301 continue;
302 }
303
304 if (PEAR::isError($err)) {
305 if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
306 $this->log(0, $err->getMessage());
307 }
308
309 $params[$i] = false;
310 if (is_object($param)) {
311 $param = $param->getChannel() . '/' . $param->getPackage();
312 }
313
314 if (!isset($this->_options['soft'])) {
315 $this->log(2, 'Package "' . $param . '" is not valid');
316 }
317
318 // Message logged above in a specific verbose mode, passing null to not show up on CLI
319 $this->pushError(null, PEAR_INSTALLER_SKIPPED);
320 } else {
321 do {
322 if ($params[$i] && $params[$i]->getType() == 'local') {
323 // bug #7090 skip channel.xml check for local packages
324 break;
325 }
326
327 if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
328 !isset($this->_options['offline'])
329 ) {
330 $channelschecked[$params[$i]->getChannel()] = true;
332 if (!class_exists('System')) {
333 require_once 'System.php';
334 }
335
336 $curchannel = $this->_registry->getChannel($params[$i]->getChannel());
337 if (PEAR::isError($curchannel)) {
339 return $this->raiseError($curchannel);
340 }
341
342 if (PEAR::isError($dir = $this->getDownloadDir())) {
344 break;
345 }
346
347 $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
348 $url = 'http://' . $mirror . '/channel.xml';
349 $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());
350
352 if ($a === false) {
353 //channel.xml not modified
354 break;
355 } else if (PEAR::isError($a)) {
356 // Attempt fallback to https automatically
357 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
358 $a = $this->downloadHttp('https://' . $mirror .
359 '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());
360
362 if (PEAR::isError($a) || !$a) {
363 break;
364 }
365 }
366 $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
367 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
368 '" to update');
369 }
370 } while (false);
371
372 if ($params[$i] && !isset($this->_options['downloadonly'])) {
373 if (isset($this->_options['packagingroot'])) {
374 $checkdir = $this->_prependPath(
375 $this->config->get('php_dir', null, $params[$i]->getChannel()),
376 $this->_options['packagingroot']);
377 } else {
378 $checkdir = $this->config->get('php_dir',
379 null, $params[$i]->getChannel());
380 }
381
382 while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
383 $checkdir = dirname($checkdir);
384 }
385
386 if ($checkdir == '.') {
387 $checkdir = '/';
388 }
389
390 if (!is_writeable($checkdir)) {
391 return PEAR::raiseError('Cannot install, php_dir for channel "' .
392 $params[$i]->getChannel() . '" is not writeable by the current user');
393 }
394 }
395 }
396 }
397
398 unset($channelschecked);
400 if (!count($params)) {
401 $a = array();
402 return $a;
403 }
404
405 if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
406 $reverify = true;
407 while ($reverify) {
408 $reverify = false;
409 foreach ($params as $i => $param) {
410 //PHP Bug 40768 / PEAR Bug #10944
411 //Nested foreaches fail in PHP 5.2.1
412 key($params);
413 $ret = $params[$i]->detectDependencies($params);
414 if (PEAR::isError($ret)) {
415 $reverify = true;
416 $params[$i] = false;
418 if (!isset($this->_options['soft'])) {
419 $this->log(0, $ret->getMessage());
420 }
421 continue 2;
422 }
423 }
424 }
425 }
426
427 if (isset($this->_options['offline'])) {
428 $this->log(3, 'Skipping dependency download check, --offline specified');
429 }
430
431 if (!count($params)) {
432 $a = array();
433 return $a;
434 }
435
438 $errorparams = array();
439 if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
440 if (count($errorparams)) {
441 foreach ($errorparams as $param) {
442 $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
443 $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
444 }
445 $a = array();
446 return $a;
447 }
448 }
449
451 if (!count($params)) {
452 $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
453 $a = array();
454 return $a;
455 }
456
457 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
458 $err = $this->analyzeDependencies($params);
459 PEAR::popErrorHandling();
460 if (!count($params)) {
461 $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
462 $a = array();
463 return $a;
464 }
465
466 $ret = array();
467 $newparams = array();
468 if (isset($this->_options['pretend'])) {
469 return $params;
470 }
471
472 $somefailed = false;
473 foreach ($params as $i => $package) {
475 $pf = &$params[$i]->download();
477 if (PEAR::isError($pf)) {
478 if (!isset($this->_options['soft'])) {
479 $this->log(1, $pf->getMessage());
480 $this->log(0, 'Error: cannot download "' .
481 $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
482 true) .
483 '"');
484 }
485 $somefailed = true;
486 continue;
487 }
488
489 $newparams[] = &$params[$i];
490 $ret[] = array(
491 'file' => $pf->getArchiveFile(),
492 'info' => &$pf,
493 'pkg' => $pf->getPackage()
494 );
495 }
496
497 if ($somefailed) {
498 // remove params that did not download successfully
499 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
500 $err = $this->analyzeDependencies($newparams, true);
501 PEAR::popErrorHandling();
502 if (!count($newparams)) {
503 $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
504 $a = array();
505 return $a;
506 }
507 }
508
509 $this->_downloadedPackages = $ret;
510 return $newparams;
511 }
const PEAR_INSTALLER_SKIPPED
const PEAR_INSTALLER_FAILED
static removeInstalled(&$params)
Definition Package.php:400
static mergeDependencies(&$params)
Definition Package.php:1346
static detectStupidDuplicates($params, &$errorparams)
Definition Package.php:1244
_prependPath($path, $prepend)
pushError($errmsg, $code=-1)
analyzeDependencies(&$params, $force=false)
const PEAR_RUNTYPE
Definition peclcmd.php:28

References _prependPath(), analyzeDependencies(), PEAR_Downloader_Package\detectStupidDuplicates(), PEAR_Common\downloadHttp(), getDownloadDir(), PEAR\isError(), PEAR_Common\log(), PEAR_Downloader_Package\mergeDependencies(), newDownloaderPackage(), PEAR_ERROR_RETURN, PEAR_INSTALLER_FAILED, PEAR_INSTALLER_SKIPPED, PEAR_RUNTYPE, pushError(), PEAR_Downloader_Package\removeDuplicates(), PEAR_Downloader_Package\removeInstalled(), PEAR\staticPopErrorHandling(), and PEAR\staticPushErrorHandling().

Here is the call graph for this function:

◆ getDependency2Object()

& getDependency2Object ( & $c,
$i,
$p,
$s )

For simpler unit-testing

Parameters
PEAR_Config
array
array
int

Definition at line 272 of file Downloader.php.

273 {
274 if (!class_exists('PEAR_Dependency2')) {
275 require_once 'PEAR/Dependency2.php';
276 }
277 $z = new PEAR_Dependency2($c, $i, $p, $s);
278 return $z;
279 }

Referenced by analyzeDependencies().

Here is the caller graph for this function:

◆ getDownloadDir()

getDownloadDir ( )

Retrieve the directory that downloads will happen in @access private

Returns
string

Definition at line 738 of file Downloader.php.

739 {
740 if (isset($this->_downloadDir)) {
741 return $this->_downloadDir;
742 }
743
744 $downloaddir = $this->config->get('download_dir');
745 if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
746 if (is_dir($downloaddir) && !is_writable($downloaddir)) {
747 $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
748 '" is not writeable. Change download_dir config variable to ' .
749 'a writeable dir to avoid this warning');
750 }
751
752 if (!class_exists('System')) {
753 require_once 'System.php';
754 }
755
756 if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
757 return $downloaddir;
758 }
759 $this->log(3, '+ tmp dir created at ' . $downloaddir);
760 }
761
762 if (!is_writable($downloaddir)) {
763 if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
764 !is_writable($downloaddir)) {
765 return PEAR::raiseError('download directory "' . $downloaddir .
766 '" is not writeable. Change download_dir config variable to ' .
767 'a writeable dir');
768 }
769 }
770
771 return $this->_downloadDir = $downloaddir;
772 }

References PEAR\isError(), and PEAR_Common\log().

Referenced by download().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getDownloadedPackages()

getDownloadedPackages ( )

Retrieve a list of downloaded packages after a call to download().

Also resets the list of downloaded packages.

Returns
array

Definition at line 1114 of file Downloader.php.

1115 {
1117 $this->_downloadedPackages = array();
1118 $this->_toDownload = array();
1119 return $ret;
1120 }

◆ getErrorMsgs()

getErrorMsgs ( )

Definition at line 1180 of file Downloader.php.

1181 {
1182 $msgs = array();
1183 $errs = $this->_errorStack;
1184 foreach ($errs as $err) {
1185 $msgs[] = $err[0];
1186 }
1187 $this->_errorStack = array();
1188 return $msgs;
1189 }

◆ getOptions()

getOptions ( )

Definition at line 801 of file Downloader.php.

802 {
803 return $this->_options;
804 }

Referenced by analyzeDependencies().

Here is the caller graph for this function:

◆ getPackageDownloadUrl()

getPackageDownloadUrl ( $package,
$version = null,
$channel = false )
Deprecated
in favor of _getPackageDownloadUrl

Definition at line 1088 of file Downloader.php.

1089 {
1090 if ($version) {
1091 $package .= "-$version";
1092 }
1093 if ($this === null || $this->_registry === null) {
1094 $package = "http://pear.php.net/get/$package";
1095 } else {
1096 $chan = $this->_registry->getChannel($channel);
1097 if (PEAR::isError($chan)) {
1098 return '';
1099 }
1100 $package = "http://" . $chan->getServer() . "/get/$package";
1101 }
1102 if (!extension_loaded("zlib")) {
1103 $package .= '?uncompress=yes';
1104 }
1105 return $package;
1106 }

References PEAR\isError().

Here is the call graph for this function:

◆ newDownloaderPackage()

newDownloaderPackage ( & $t)

For simpler unit-testing

Parameters
PEAR_Downloader
Returns
PEAR_Downloader_Package

Definition at line 256 of file Downloader.php.

257 {
258 if (!class_exists('PEAR_Downloader_Package')) {
259 require_once 'PEAR/Downloader/Package.php';
260 }
261 $a = new PEAR_Downloader_Package($t);
262 return $a;
263 }

Referenced by _getDepPackageDownloadUrl(), and download().

Here is the caller graph for this function:

◆ pushError()

pushError ( $errmsg,
$code = -1 )
Parameters
string
integer

Definition at line 1175 of file Downloader.php.

1176 {
1177 array_push($this->_errorStack, array($errmsg, $code));
1178 }

Referenced by download().

Here is the caller graph for this function:

◆ setDownloadDir()

setDownloadDir ( $dir)

Definition at line 774 of file Downloader.php.

775 {
776 if (!@is_writable($dir)) {
777 if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
778 return PEAR::raiseError('download directory "' . $dir .
779 '" is not writeable. Change download_dir config variable to ' .
780 'a writeable dir');
781 }
782 }
783 $this->_downloadDir = $dir;
784 }

References PEAR\isError().

Here is the call graph for this function:

◆ setOptions()

setOptions ( $options)

Reimplemented in PEAR_Installer.

Definition at line 796 of file Downloader.php.

797 {
798 $this->_options = $options;
799 }

References $options.

◆ sortPackagesForInstall()

sortPackagesForInstall ( & $packages)

Sort a list of arrays of array(downloaded packagefilename) by dependency.

This uses the topological sort method from graph theory, and the Structures_Graph package to properly sort dependencies for installation.

Parameters
arrayan array of downloaded PEAR_Downloader_Packages
Returns
array array of array(packagefilename, package.xml contents)

Definition at line 1211 of file Downloader.php.

1212 {
1213 require_once 'Structures/Graph.php';
1214 require_once 'Structures/Graph/Node.php';
1215 require_once 'Structures/Graph/Manipulator/TopologicalSorter.php';
1216 $depgraph = new Structures_Graph(true);
1217 $nodes = array();
1218 $reg = &$this->config->getRegistry();
1219 foreach ($packages as $i => $package) {
1220 $pname = $reg->parsedPackageNameToString(
1221 array(
1222 'channel' => $package->getChannel(),
1223 'package' => strtolower($package->getPackage()),
1224 ));
1225 $nodes[$pname] = new Structures_Graph_Node;
1226 $nodes[$pname]->setData($packages[$i]);
1227 $depgraph->addNode($nodes[$pname]);
1228 }
1229
1230 $deplinks = array();
1231 foreach ($nodes as $package => $node) {
1232 $pf = &$node->getData();
1233 $pdeps = $pf->getDeps(true);
1234 if (!$pdeps) {
1235 continue;
1236 }
1237
1238 if ($pf->getPackagexmlVersion() == '1.0') {
1239 foreach ($pdeps as $dep) {
1240 if ($dep['type'] != 'pkg' ||
1241 (isset($dep['optional']) && $dep['optional'] == 'yes')) {
1242 continue;
1243 }
1244
1245 $dname = $reg->parsedPackageNameToString(
1246 array(
1247 'channel' => 'pear.php.net',
1248 'package' => strtolower($dep['name']),
1249 ));
1250
1251 if (isset($nodes[$dname])) {
1252 if (!isset($deplinks[$dname])) {
1253 $deplinks[$dname] = array();
1254 }
1255
1256 $deplinks[$dname][$package] = 1;
1257 // dependency is in installed packages
1258 continue;
1259 }
1260
1261 $dname = $reg->parsedPackageNameToString(
1262 array(
1263 'channel' => 'pecl.php.net',
1264 'package' => strtolower($dep['name']),
1265 ));
1266
1267 if (isset($nodes[$dname])) {
1268 if (!isset($deplinks[$dname])) {
1269 $deplinks[$dname] = array();
1270 }
1271
1272 $deplinks[$dname][$package] = 1;
1273 // dependency is in installed packages
1274 continue;
1275 }
1276 }
1277 } else {
1278 // the only ordering we care about is:
1279 // 1) subpackages must be installed before packages that depend on them
1280 // 2) required deps must be installed before packages that depend on them
1281 if (isset($pdeps['required']['subpackage'])) {
1282 $t = $pdeps['required']['subpackage'];
1283 if (!isset($t[0])) {
1284 $t = array($t);
1285 }
1286
1287 $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1288 }
1289
1290 if (isset($pdeps['group'])) {
1291 if (!isset($pdeps['group'][0])) {
1292 $pdeps['group'] = array($pdeps['group']);
1293 }
1294
1295 foreach ($pdeps['group'] as $group) {
1296 if (isset($group['subpackage'])) {
1297 $t = $group['subpackage'];
1298 if (!isset($t[0])) {
1299 $t = array($t);
1300 }
1301
1302 $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1303 }
1304 }
1305 }
1306
1307 if (isset($pdeps['optional']['subpackage'])) {
1308 $t = $pdeps['optional']['subpackage'];
1309 if (!isset($t[0])) {
1310 $t = array($t);
1311 }
1312
1313 $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1314 }
1315
1316 if (isset($pdeps['required']['package'])) {
1317 $t = $pdeps['required']['package'];
1318 if (!isset($t[0])) {
1319 $t = array($t);
1320 }
1321
1322 $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1323 }
1324
1325 if (isset($pdeps['group'])) {
1326 if (!isset($pdeps['group'][0])) {
1327 $pdeps['group'] = array($pdeps['group']);
1328 }
1329
1330 foreach ($pdeps['group'] as $group) {
1331 if (isset($group['package'])) {
1332 $t = $group['package'];
1333 if (!isset($t[0])) {
1334 $t = array($t);
1335 }
1336
1337 $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1338 }
1339 }
1340 }
1341 }
1342 }
1343
1344 $this->_detectDepCycle($deplinks);
1345 foreach ($deplinks as $dependent => $parents) {
1346 foreach ($parents as $parent => $unused) {
1347 $nodes[$dependent]->connectTo($nodes[$parent]);
1348 }
1349 }
1350
1352 $ret = array();
1353 for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
1354 foreach ($installOrder[$i] as $index => $sortedpackage) {
1355 $data = &$installOrder[$i][$index]->getData();
1356 $ret[] = &$nodes[$reg->parsedPackageNameToString(
1357 array(
1358 'channel' => $data->getChannel(),
1359 'package' => strtolower($data->getPackage()),
1360 ))]->getData();
1361 }
1362 }
1363
1364 $packages = $ret;
1365 return;
1366 }
_detectDepCycle(&$deplinks)
_setupGraph($t, $reg, &$deplinks, &$nodes, $package)

References _detectDepCycle(), _setupGraph(), Structures_Graph_Node\setData(), and Structures_Graph_Manipulator_TopologicalSorter\sort().

Referenced by sortPkgDeps().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sortPkgDeps()

sortPkgDeps ( & $packages,
$uninstall = false )

for BC

Deprecated

Definition at line 1196 of file Downloader.php.

1197 {
1198 $uninstall ?
1199 $this->sortPackagesForUninstall($packages) :
1200 $this->sortPackagesForInstall($packages);
1201 }
sortPackagesForInstall(&$packages)

References sortPackagesForInstall().

Here is the call graph for this function:

Field Documentation

◆ $_downloadDir

$_downloadDir

Definition at line 142 of file Downloader.php.

◆ $_downloadedPackages

$_downloadedPackages = array()

Definition at line 90 of file Downloader.php.

◆ $_errorStack

$_errorStack = array()

Definition at line 123 of file Downloader.php.

◆ $_installed

$_installed = array()

Definition at line 117 of file Downloader.php.

◆ $_internalDownload

$_internalDownload = false

Definition at line 129 of file Downloader.php.

◆ $_options

$_options

Definition at line 75 of file Downloader.php.

◆ $_packageSortTree

$_packageSortTree

Definition at line 136 of file Downloader.php.

◆ $_preferredState

$_preferredState

Definition at line 59 of file Downloader.php.

◆ $_registry

$_registry

Definition at line 52 of file Downloader.php.

Referenced by PEAR_Installer\install().

◆ $_toDownload

$_toDownload = array()

Definition at line 106 of file Downloader.php.

◆ $bivalentMethods

$bivalentMethods
staticprotected
Initial value:
= array(
'setErrorHandling' => true,
'raiseError' => true,
'throwError' => true,
'pushErrorHandling' => true,
'popErrorHandling' => true,
'downloadHttp' => true,
)

Definition at line 148 of file Downloader.php.


The documentation for this class was generated from the following file:
  • E:/Bearsampp-development/sandbox/core/libs/php/pear/pear/PEAR/Downloader.php