diff options
author | Greg Beaver <cellog@php.net> | 2006-05-22 10:19:34 +0000 |
---|---|---|
committer | Greg Beaver <cellog@php.net> | 2006-05-22 10:19:34 +0000 |
commit | 5fb5cfdbca3a21414050638313549789c42bdac2 (patch) | |
tree | 32f42818a9a50655e9bda01cdaf1975fc854979d | |
parent | 4d0daac7384de9be60d7976523083e6a9fc13ab9 (diff) | |
download | php-git-5fb5cfdbca3a21414050638313549789c42bdac2.tar.gz |
sync to PEAR 1.4.9
add PEAR 1.4.9 to installed tarballs
29 files changed, 643 insertions, 334 deletions
diff --git a/pear/PEAR.php b/pear/PEAR.php index 7b3d64c268..4c909f8bf0 100644 --- a/pear/PEAR.php +++ b/pear/PEAR.php @@ -247,6 +247,12 @@ class PEAR */ function registerShutdownFunc($func, $args = array()) { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); } diff --git a/pear/PEAR/ChannelFile.php b/pear/PEAR/ChannelFile.php index adb4f052e0..16c4ab87c2 100644 --- a/pear/PEAR/ChannelFile.php +++ b/pear/PEAR/ChannelFile.php @@ -324,6 +324,20 @@ class PEAR_ChannelFile { } return $a; } + + /** + * Unlike {@link fromArray()} this does not do any validation + * @param array + * @static + * @return PEAR_ChannelFile + */ + function &fromArrayWithErrors($data, $compatibility = false, + $stackClass = 'PEAR_ErrorStack') + { + $a = new PEAR_ChannelFile($compatibility, $stackClass); + $a->_fromArray($data); + return $a; + } /** * @param array diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php index a08c869e8d..0799527aa9 100644 --- a/pear/PEAR/Command/Install.php +++ b/pear/PEAR/Command/Install.php @@ -230,11 +230,6 @@ More than one package may be specified at once. 'arg' => 'DIR', 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', ), - 'packagingroot' => array( - 'shortopt' => 'P', - 'arg' => 'DIR', - 'doc' => 'root directory used when packaging files, like RPM packaging', - ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', ), @@ -376,6 +371,9 @@ Run post-installation scripts in package <package>, if any exist. } $this->config->set('default_channel', $channel); $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $dorest = true; @@ -541,23 +539,29 @@ Run post-installation scripts in package <package>, if any exist. $group['attribs']['hint'] . ')'); } $extrainfo[] = 'To install use "pear install ' . - $param->getPackage() . '#featurename"'; + $reg->parsedPackageNameToString( + array('package' => $param->getPackage(), + 'channel' => $param->getChannel()), true) . + '#featurename"'; } } if (isset($options['installroot'])) { $reg = &$this->config->getRegistry(); } $pkg = &$reg->getPackage($param->getPackage(), $param->getChannel()); - $pkg->setConfig($this->config); - if ($list = $pkg->listPostinstallScripts()) { - $pn = $reg->parsedPackageNameToString(array('channel' => - $param->getChannel(), 'package' => $param->getPackage()), true); - $extrainfo[] = $pn . ' has post-install scripts:'; - foreach ($list as $file) { - $extrainfo[] = $file; + // $pkg may be NULL if install is a 'fake' install via --packagingroot + if (is_object($pkg)) { + $pkg->setConfig($this->config); + if ($list = $pkg->listPostinstallScripts()) { + $pn = $reg->parsedPackageNameToString(array('channel' => + $param->getChannel(), 'package' => $param->getPackage()), true); + $extrainfo[] = $pn . ' has post-install scripts:'; + foreach ($list as $file) { + $extrainfo[] = $file; + } + $extrainfo[] = 'Use "pear run-scripts ' . $pn . '" to run'; + $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } - $extrainfo[] = 'Use "pear run-scripts ' . $pn . '" to run'; - $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } } else { return $this->raiseError("$command failed"); diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php index adbac84853..23f10efcbb 100644 --- a/pear/PEAR/Common.php +++ b/pear/PEAR/Common.php @@ -47,11 +47,11 @@ define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PRE define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . '$/'); -define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9_\.]+'); +define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '$/'); // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED -define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(\/[a-zA-Z0-9-]+)*'); +define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '$/i'); define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' diff --git a/pear/PEAR/Config.php b/pear/PEAR/Config.php index eaeff0f990..64011fee75 100644 --- a/pear/PEAR/Config.php +++ b/pear/PEAR/Config.php @@ -1265,6 +1265,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } @@ -1286,6 +1289,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } @@ -1329,6 +1335,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($ret) && $chan->getName() != $ret) { return $channel; // mirror does not exist } @@ -1383,6 +1392,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net'); + if (PEAR::isError($chan)) { + return false; + } if (!$chan->getMirror($value) && $chan->getName() != $value) { return false; // mirror does not exist } diff --git a/pear/PEAR/Dependency2.php b/pear/PEAR/Dependency2.php index 423dc5b270..8c61b15a29 100644 --- a/pear/PEAR/Dependency2.php +++ b/pear/PEAR/Dependency2.php @@ -525,7 +525,7 @@ class PEAR_Dependency2 */ function getPEARVersion() { - return '1.4.3'; + return '1.4.9'; } function validatePearinstallerDependency($dep) diff --git a/pear/PEAR/Downloader.php b/pear/PEAR/Downloader.php index 08a35c0016..1846f71055 100644 --- a/pear/PEAR/Downloader.php +++ b/pear/PEAR/Downloader.php @@ -278,6 +278,10 @@ class PEAR_Downloader extends PEAR_Common PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $params[$i]->initialize($param); PEAR::staticPopErrorHandling(); + if (!$err) { + // skip parameters that were missed by preferred_state + continue; + } if (PEAR::isError($err)) { if (!isset($this->_options['soft'])) { $this->log(0, $err->getMessage()); @@ -297,6 +301,10 @@ class PEAR_Downloader extends PEAR_Common require_once 'System.php'; } $curchannel = &$this->_registry->getChannel($params[$i]->getChannel()); + if (PEAR::isError($curchannel)) { + PEAR::staticPopErrorHandling(); + return $this->raiseError($curchannel); + } $a = $this->downloadHttp('http://' . $params[$i]->getChannel() . '/channel.xml', $this->ui, System::mktemp(array('-d')), null, $curchannel->lastModified()); @@ -309,7 +317,14 @@ class PEAR_Downloader extends PEAR_Common '" to update'); } if ($params[$i] && !isset($this->_options['downloadonly'])) { - $checkdir = $this->config->get('php_dir', null, $params[$i]->getChannel()); + if (isset($this->_options['packagingroot'])) { + $checkdir = $this->_prependPath( + $this->config->get('php_dir', null, $params[$i]->getChannel()), + $this->_options['packagingroot']); + } else { + $checkdir = $this->config->get('php_dir', + null, $params[$i]->getChannel()); + } while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) { $checkdir = dirname($checkdir); } @@ -703,10 +718,14 @@ class PEAR_Downloader extends PEAR_Common break; } } + $this->configSet('default_channel', $curchannel); return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); } while (false); } $chan = &$this->_registry->getChannel($parr['channel']); + if (PEAR::isError($chan)) { + return $chan; + } $version = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']); if ($chan->supportsREST($this->config->get('preferred_mirror')) && @@ -719,6 +738,7 @@ class PEAR_Downloader extends PEAR_Common $url = $rest->getDownloadURL($base, $parr, $state, false); } if (PEAR::isError($url)) { + $this->configSet('default_channel', $curchannel); return $url; } if ($parr['channel'] != $curchannel) { @@ -844,6 +864,9 @@ class PEAR_Downloader extends PEAR_Common unset($parr['state']); } $chan = &$this->_registry->getChannel($remotechannel); + if (PEAR::isError($chan)) { + return $chan; + } $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel); if ($chan->supportsREST($this->config->get('preferred_mirror')) && @@ -951,6 +974,9 @@ class PEAR_Downloader extends PEAR_Common $package = "http://pear.php.net/get/$package"; } else { $chan = $this->_registry->getChannel($channel); + if (PEAR::isError($chan)) { + return ''; + } $package = "http://" . $chan->getServer() . "/get/$package"; } if (!extension_loaded("zlib")) { @@ -1277,6 +1303,10 @@ class PEAR_Downloader extends PEAR_Common function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, $accept = false) { + static $redirect = 0; + // allways reset , so we are clean case of error + $wasredirect = $redirect; + $redirect = 0; if ($callback) { call_user_func($callback, 'setup', array(&$ui)); } @@ -1385,18 +1415,33 @@ class PEAR_Downloader extends PEAR_Common $request .= "\r\n"; fwrite($fp, $request); $headers = array(); + $reply = 0; while (trim($line = fgets($fp, 1024))) { if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { $headers[strtolower($matches[1])] = trim($matches[2]); } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { - if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) { + $reply = (int) $matches[1]; + if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { return false; } - if ($matches[1] != 200) { + if (! in_array($reply, array(200, 301, 302, 303, 305, 307))) { return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); } } } + if ($reply != 200) { + if (isset($headers['location'])) { + if ($wasredirect < 5) { + $redirect = $wasredirect + 1; + return $this->downloadHttp($headers['location'], + $ui, $save_dir, $callback, $lastmodified, $accept); + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirection looped more than 5 times)"); + } + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirected but no location)"); + } + } if (isset($headers['content-disposition']) && preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { $save_as = basename($matches[1]); diff --git a/pear/PEAR/Downloader/Package.php b/pear/PEAR/Downloader/Package.php index 725b712f66..de882bf873 100644 --- a/pear/PEAR/Downloader/Package.php +++ b/pear/PEAR/Downloader/Package.php @@ -20,6 +20,11 @@ * @since File available since Release 1.4.0a1 */ /** + * Error code when parameter initialization fails because no releases + * exist within preferred_state, but releases do exist + */ +define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); +/** * Coordinates download parameters and manages their dependencies * prior to downloading them. * @@ -174,6 +179,10 @@ class PEAR_Downloader_Package } $err = $this->_fromString($param); if (PEAR::isError($err) || !$this->_valid) { + if (PEAR::isError($err) && + $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { + return false; // instruct the downloader to silently skip + } if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) { if (is_array($origErr->getUserInfo())) { @@ -209,6 +218,7 @@ class PEAR_Downloader_Package } } } + return true; } /** @@ -1522,7 +1532,11 @@ class PEAR_Downloader_Package $this->_registry->parsedPackageNameToString($pname, true) . ' can be installed with "pecl install ' . $pname['package'] . '"'); + } else { + $pname['channel'] = 'pear.php.net'; } + } else { + $pname['channel'] = 'pear.php.net'; } } return $info; @@ -1672,6 +1686,22 @@ class PEAR_Downloader_Package $vs = ' within preferred state "' . $this->_downloader->config->get( 'preferred_state') . '"'; } + $options = $this->_downloader->getOptions(); + // this is only set by the "download-all" command + if (isset($options['ignorepreferred_state'])) { + $err = PEAR::raiseError( + 'Failed to download ' . $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package']), + true) + . $vs . + ', latest release is version ' . $info['version'] . + ', stability "' . $info['info']->getState() . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['version'])) . '" to install', + PEAR_DOWNLOADER_PACKAGE_STATE); + return $err; + } $err = PEAR::raiseError( 'Failed to download ' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package']), diff --git a/pear/PEAR/Frontend.php b/pear/PEAR/Frontend.php index c9ea58f93f..15135f72e3 100644 --- a/pear/PEAR/Frontend.php +++ b/pear/PEAR/Frontend.php @@ -34,6 +34,9 @@ $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null; /** * Singleton-based frontend for PEAR user input/output + * + * Note that frontend classes must implement userConfirm(), and shoul implement + * displayFatalError() and outputData() * @category pear * @package PEAR * @author Greg Beaver <cellog@php.net> @@ -64,6 +67,15 @@ class PEAR_Frontend extends PEAR } } + /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to conform to the PEAR naming standard of + * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php) + * @param string $uiclass full class name + * @return PEAR_Frontend + * @static + */ function &setFrontendClass($uiclass) { if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && @@ -94,6 +106,38 @@ class PEAR_Frontend extends PEAR } /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to be a descendant of PEAR_Frontend + * @param PEAR_Frontend + * @return PEAR_Frontend + * @static + */ + function &setFrontendObject($uiobject) + { + if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && + is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) { + return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; + } + if (!is_a($uiobject, 'PEAR_Frontend')) { + $err = PEAR::raiseError('not a valid frontend class: (' . + get_class($uiobject) . ')'); + return $err; + } + // quick test to see if this class implements a few of the most + // important frontend methods + if (method_exists($uiobject, 'userConfirm')) { + $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject; + $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject); + return $uiobject; + } else { + $err = PEAR::raiseError("not a value frontend class: (" . get_class($uiobject) + . ')'); + return $err; + } + } + + /** * @param string $path relative or absolute include path * @return boolean * @static @@ -135,7 +179,7 @@ class PEAR_Frontend extends PEAR $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } - function log($level, $msg, $append_crlf = true) + function log($msg, $append_crlf = true) { } } diff --git a/pear/PEAR/Frontend/CLI.php b/pear/PEAR/Frontend/CLI.php index af50657ec1..a3e58353ef 100644 --- a/pear/PEAR/Frontend/CLI.php +++ b/pear/PEAR/Frontend/CLI.php @@ -455,12 +455,17 @@ class PEAR_Frontend_CLI extends PEAR_Frontend } else { $w = strlen($col); } - if ($w > @$this->params['widest'][$i]) { + + if (isset($this->params['widest'][$i])) { + if ($w > $this->params['widest'][$i]) { + $this->params['widest'][$i] = $w; + } + } else { $this->params['widest'][$i] = $w; } $tmp = count_chars($columns[$i], 1); // handle unix, mac and windows formats - $lines = (isset($tmp[10]) ? $tmp[10] : @$tmp[13]) + 1; + $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1; if ($lines > $highest) { $highest = $lines; } diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index c8dfcde9ef..8bce160ae1 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -295,147 +295,150 @@ class PEAR_Installer extends PEAR_Downloader $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); // }}} - if (!@is_dir($dest_dir)) { + if (empty($this->_options['register-only']) && !@is_dir($dest_dir)) { if (!$this->mkDirHier($dest_dir)) { return $this->raiseError("failed to mkdir $dest_dir", PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $dest_dir"); } - if (empty($atts['replacements'])) { - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file", - PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $orig_file $dest_file"); - if (isset($atts['md5sum'])) { - $md5sum = md5_file($dest_file); - } - } else { - // {{{ file with replacements - if (!file_exists($orig_file)) { - return $this->raiseError("file does not exist", - PEAR_INSTALLER_FAILED); - } - if (function_exists('file_get_contents')) { - $contents = file_get_contents($orig_file); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (empty($atts['replacements'])) { + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($atts['md5sum'])) { + $md5sum = md5_file($dest_file); + } } else { - $fp = fopen($orig_file, "r"); - $contents = @fread($fp, filesize($orig_file)); - fclose($fp); - } - if ($contents === false) { - $contents = ''; - } - if (isset($atts['md5sum'])) { - $md5sum = md5($contents); - } - $subst_from = $subst_to = array(); - foreach ($atts['replacements'] as $a) { - $to = ''; - if ($a['type'] == 'php-const') { - if (preg_match('/^[a-z0-9_]+$/i', $a['to'])) { - eval("\$to = $a[to];"); - } else { - if (!isset($options['soft'])) { - $this->log(0, "invalid php-const replacement: $a[to]"); + // {{{ file with replacements + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + if (function_exists('file_get_contents')) { + $contents = file_get_contents($orig_file); + } else { + $fp = fopen($orig_file, "r"); + $contents = @fread($fp, filesize($orig_file)); + fclose($fp); + } + if ($contents === false) { + $contents = ''; + } + if (isset($atts['md5sum'])) { + $md5sum = md5($contents); + } + $subst_from = $subst_to = array(); + foreach ($atts['replacements'] as $a) { + $to = ''; + if ($a['type'] == 'php-const') { + if (preg_match('/^[a-z0-9_]+$/i', $a['to'])) { + eval("\$to = $a[to];"); + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid php-const replacement: $a[to]"); + } + continue; } - continue; - } - } elseif ($a['type'] == 'pear-config') { - if ($a['to'] == 'master_server') { - $chan = $this->_registry->getChannel($channel); - if ($chan) { - $to = $chan->getServer(); + } elseif ($a['type'] == 'pear-config') { + if ($a['to'] == 'master_server') { + $chan = $this->_registry->getChannel($channel); + if (!PEAR::isError($chan)) { + $to = $chan->getServer(); + } else { + $to = $this->config->get($a['to'], null, $channel); + } } else { $to = $this->config->get($a['to'], null, $channel); } - } else { - $to = $this->config->get($a['to'], null, $channel); - } - if (is_null($to)) { - if (!isset($options['soft'])) { - $this->log(0, "invalid pear-config replacement: $a[to]"); + if (is_null($to)) { + if (!isset($options['soft'])) { + $this->log(0, "invalid pear-config replacement: $a[to]"); + } + continue; } - continue; - } - } elseif ($a['type'] == 'package-info') { - if ($t = $this->pkginfo->packageInfo($a['to'])) { - $to = $t; - } else { - if (!isset($options['soft'])) { - $this->log(0, "invalid package-info replacement: $a[to]"); + } elseif ($a['type'] == 'package-info') { + if ($t = $this->pkginfo->packageInfo($a['to'])) { + $to = $t; + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid package-info replacement: $a[to]"); + } + continue; } - continue; + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; } } - if (!is_null($to)) { - $subst_from[] = $a['from']; - $subst_to[] = $to; + $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); } - } - $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); - if (sizeof($subst_from)) { - $contents = str_replace($subst_from, $subst_to, $contents); - } - $wp = @fopen($dest_file, "wb"); - if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - if (fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - fclose($wp); - // }}} - } - // {{{ check the md5 - if (isset($md5sum)) { - if (strtolower($md5sum) == strtolower($atts['md5sum'])) { - $this->log(2, "md5sum ok: $final_dest_file"); - } else { - if (empty($options['force'])) { - // delete the file - @unlink($dest_file); - if (!isset($options['ignore-errors'])) { - return $this->raiseError("bad md5sum for file $final_dest_file", + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", PEAR_INSTALLER_FAILED); + } + fclose($wp); + // }}} + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) == strtolower($atts['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + @unlink($dest_file); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($atts['role'] == 'script') { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { - $this->log(0, "warning : bad md5sum for file $final_dest_file"); + $this->log(0, "failed to change mode of $dest_file"); } } } + // }}} + $this->addFileOperation("rename", array($dest_file, $final_dest_file, + $atts['role'] == 'ext')); } - // }}} - // {{{ set file permissions - if (!OS_WINDOWS) { - if ($atts['role'] == 'script') { - $mode = 0777 & ~(int)octdec($this->config->get('umask')); - $this->log(3, "+ chmod +x $dest_file"); - } else { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - } - $this->addFileOperation("chmod", array($mode, $dest_file)); - if (!@chmod($dest_file, $mode)) { - if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file"); - } - } - } - // }}} - $this->addFileOperation("rename", array($dest_file, $final_dest_file, - $atts['role'] == 'ext')); // Store the full path where the file was installed for easy unistall $this->addFileOperation("installed_as", array($file, $installed_as, $save_destdir, dirname(substr($installedas_dest_file, strlen($save_destdir))))); @@ -491,114 +494,119 @@ class PEAR_Installer extends PEAR_Downloader $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); // }}} - if (!@is_dir($dest_dir)) { - if (!$this->mkDirHier($dest_dir)) { - return $this->raiseError("failed to mkdir $dest_dir", - PEAR_INSTALLER_FAILED); + if (empty($this->_options['register-only'])) { + if (!@is_dir($dest_dir)) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); } - $this->log(3, "+ mkdir $dest_dir"); } $attribs = $atts['attribs']; unset($atts['attribs']); - if (!count($atts)) { // no tasks - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file", - PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $orig_file $dest_file"); - if (isset($attribs['md5sum'])) { - $md5sum = md5_file($dest_file); - } - } else { // file with tasks - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (function_exists('file_get_contents')) { - $contents = file_get_contents($orig_file); - } else { - $fp = fopen($orig_file, "r"); - $contents = @fread($fp, filesize($orig_file)); // filesize can be 0 - fclose($fp); - } - if ($contents === false) { - $contents = ''; - } - if (isset($attribs['md5sum'])) { - $md5sum = md5($contents); - } - foreach ($atts as $tag => $raw) { - $tag = str_replace($pkg->getTasksNs() . ':', '', $tag); - $task = "PEAR_Task_$tag"; - $task = &new $task($this->config, $this, PEAR_TASK_INSTALL); - if (!$task->isScript()) { // scripts are only handled after installation - $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); - $res = $task->startSession($pkg, $contents, $final_dest_file); - if ($res === false) { - continue; // skip this file - } - if (PEAR::isError($res)) { - return $res; - } - $contents = $res; // save changes + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!count($atts)) { // no tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); } - $wp = @fopen($dest_file, "wb"); - if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file", PEAR_INSTALLER_FAILED); } - if (fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($attribs['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { // file with tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", PEAR_INSTALLER_FAILED); } - fclose($wp); - } - } - // {{{ check the md5 - if (isset($md5sum)) { - if (strtolower($md5sum) == strtolower($attribs['md5sum'])) { - $this->log(2, "md5sum ok: $final_dest_file"); - } else { - if (empty($options['force'])) { - // delete the file - @unlink($dest_file); - if (!isset($options['ignore-errors'])) { - return $this->raiseError("bad md5sum for file $final_dest_file", + if (function_exists('file_get_contents')) { + $contents = file_get_contents($orig_file); + } else { + $fp = fopen($orig_file, "r"); + $contents = @fread($fp, filesize($orig_file)); // filesize can be 0 + fclose($fp); + } + if ($contents === false) { + $contents = ''; + } + if (isset($attribs['md5sum'])) { + $md5sum = md5($contents); + } + foreach ($atts as $tag => $raw) { + $tag = str_replace($pkg->getTasksNs() . ':', '', $tag); + $task = "PEAR_Task_$tag"; + $task = &new $task($this->config, $this, PEAR_TASK_INSTALL); + if (!$task->isScript()) { // scripts are only handled after installation + $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); + $res = $task->startSession($pkg, $contents, $final_dest_file); + if ($res === false) { + continue; // skip this file + } + if (PEAR::isError($res)) { + return $res; + } + $contents = $res; // save changes + } + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", PEAR_INSTALLER_FAILED); + } + fclose($wp); + } + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) == strtolower($attribs['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + @unlink($dest_file); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($role->isExecutable()) { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { - $this->log(0, "warning : bad md5sum for file $final_dest_file"); + $this->log(0, "failed to change mode of $dest_file"); } } } + // }}} + $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); } - // }}} - // {{{ set file permissions - if (!OS_WINDOWS) { - if ($role->isExecutable()) { - $mode = 0777 & ~(int)octdec($this->config->get('umask')); - $this->log(3, "+ chmod +x $dest_file"); - } else { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - } - $this->addFileOperation("chmod", array($mode, $dest_file)); - if (!@chmod($dest_file, $mode)) { - if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file"); - } - } - } - // }}} - $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); // Store the full path where the file was installed for easy uninstall $this->addFileOperation("installed_as", array($file, $installed_as, $save_destdir, dirname(substr($dest_file, strlen($save_destdir))))); @@ -995,7 +1003,7 @@ class PEAR_Installer extends PEAR_Downloader $channel = $pkg->getChannel(); if (isset($this->_options['packagingroot'])) { $packrootphp_dir = $this->_prependPath( - $this->config->get('php_dir', null, 'pear.php.net'), + $this->config->get('php_dir', null, $channel), $this->_options['packagingroot']); } @@ -1004,6 +1012,7 @@ class PEAR_Installer extends PEAR_Downloader $this->_registry = &$this->config->getRegistry(); $installregistry = &$this->_registry; $this->installroot = ''; // all done automagically now + $php_dir = $this->config->get('php_dir', null, $channel); } else { $this->config->setInstallRoot(false); $this->_registry = &$this->config->getRegistry(); @@ -1156,71 +1165,69 @@ class PEAR_Installer extends PEAR_Downloader $this->source_files = 0; $savechannel = $this->config->get('default_channel'); - if (empty($options['register-only'])) { - if (!is_dir($php_dir)) { - if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { - return $this->raiseError("no installation destination directory '$php_dir'\n"); - } + if (empty($options['register-only']) && !is_dir($php_dir)) { + if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { + return $this->raiseError("no installation destination directory '$php_dir'\n"); } + } - $tmp_path = dirname($descfile); - if (substr($pkgfile, -4) != '.xml') { - $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); - } + $tmp_path = dirname($descfile); + if (substr($pkgfile, -4) != '.xml') { + $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); + } - $this->configSet('default_channel', $channel); - // {{{ install files - - if ($pkg->getPackagexmlVersion() == '2.0') { - $filelist = $pkg->getInstallationFilelist(); + $this->configSet('default_channel', $channel); + // {{{ install files + + if ($pkg->getPackagexmlVersion() == '2.0') { + $filelist = $pkg->getInstallationFilelist(); + } else { + $filelist = $pkg->getFileList(); + } + if (PEAR::isError($filelist)) { + return $filelist; + } + $pkg->resetFilelist(); + $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), + 'version', $pkg->getChannel())); + foreach ($filelist as $file => $atts) { + if ($pkg->getPackagexmlVersion() == '1.0') { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile($file, $atts, $tmp_path, $options); + $this->popExpect(); } else { - $filelist = $pkg->getFileList(); - } - if (PEAR::isError($filelist)) { - return $filelist; - } - $pkg->resetFilelist(); - $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), - 'version', $pkg->getChannel())); - foreach ($filelist as $file => $atts) { - if ($pkg->getPackagexmlVersion() == '1.0') { - $this->expectError(PEAR_INSTALLER_FAILED); - $res = $this->_installFile($file, $atts, $tmp_path, $options); - $this->popExpect(); + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options); + $this->popExpect(); + } + if (PEAR::isError($res)) { + if (empty($options['ignore-errors'])) { + $this->rollbackFileTransaction(); + if ($res->getMessage() == "file does not exist") { + $this->raiseError("file $file in package.xml does not exist"); + } + return $this->raiseError($res); } else { - $this->expectError(PEAR_INSTALLER_FAILED); - $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options); - $this->popExpect(); - } - if (PEAR::isError($res)) { - if (empty($options['ignore-errors'])) { - $this->rollbackFileTransaction(); - if ($res->getMessage() == "file does not exist") { - $this->raiseError("file $file in package.xml does not exist"); - } - return $this->raiseError($res); - } else { - if (!isset($options['soft'])) { - $this->log(0, "Warning: " . $res->getMessage()); - } + if (!isset($options['soft'])) { + $this->log(0, "Warning: " . $res->getMessage()); } } - if ($res == PEAR_INSTALLER_OK) { - // Register files that were installed - $pkg->installedFile($file, $atts); - } } - // }}} + if ($res == PEAR_INSTALLER_OK) { + // Register files that were installed + $pkg->installedFile($file, $atts); + } + } + // }}} - // {{{ compile and install source files - if ($this->source_files > 0 && empty($options['nobuild'])) { - if (PEAR::isError($err = - $this->_compileSourceFiles($savechannel, $pkg))) { - return $err; - } + // {{{ compile and install source files + if ($this->source_files > 0 && empty($options['nobuild'])) { + if (PEAR::isError($err = + $this->_compileSourceFiles($savechannel, $pkg))) { + return $err; } - // }}} } + // }}} if (isset($backedup)) { $this->_removeBackups($backedup); @@ -1326,27 +1333,34 @@ class PEAR_Installer extends PEAR_Downloader } $dest = $ext['dest']; $this->log(1, "Installing '$ext[file]'"); - $copyto = $this->_prependPath($dest, $this->installroot); + $packagingroot = ''; + if (isset($this->_options['packagingroot'])) { + $packagingroot = $this->_options['packagingroot']; + } + $copyto = $this->_prependPath($dest, $packagingroot); $copydir = dirname($copyto); - if (!@is_dir($copydir)) { - if (!$this->mkDirHier($copydir)) { - return $this->raiseError("failed to mkdir $copydir", - PEAR_INSTALLER_FAILED); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!@is_dir($copydir)) { + if (!$this->mkDirHier($copydir)) { + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $copydir"); } - $this->log(3, "+ mkdir $copydir"); - } - if (!@copy($ext['file'], $copyto)) { - return $this->raiseError("failed to write $copyto", PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $ext[file] $copyto"); - if (!OS_WINDOWS) { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - $this->addFileOperation('chmod', array($mode, $copyto)); - if (!@chmod($copyto, $mode)) { - $this->log(0, "failed to change mode of $copyto"); + if (!@copy($ext['file'], $copyto)) { + return $this->raiseError("failed to write $copyto", PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $ext[file] $copyto"); + if (!OS_WINDOWS) { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + $this->addFileOperation('chmod', array($mode, $copyto)); + if (!@chmod($copyto, $mode)) { + $this->log(0, "failed to change mode of $copyto"); + } } + $this->addFileOperation('rename', array($ext['file'], $copyto)); } - $this->addFileOperation('rename', array($ext['file'], $copyto)); if ($filelist->getPackageXmlVersion() == '1.0') { $filelist->installedFile($bn, array( diff --git a/pear/PEAR/PackageFile.php b/pear/PEAR/PackageFile.php index 6f677a35c5..3420f5a869 100644 --- a/pear/PEAR/PackageFile.php +++ b/pear/PEAR/PackageFile.php @@ -332,7 +332,7 @@ class PEAR_PackageFile $xml = $name; break; } elseif (ereg('package.xml$', $name, $match)) { - $xml = $match[0]; + $xml = $name; break; } } diff --git a/pear/PEAR/PackageFile/v1.php b/pear/PEAR/PackageFile/v1.php index eb87c5b109..09431e262e 100644 --- a/pear/PEAR/PackageFile/v1.php +++ b/pear/PEAR/PackageFile/v1.php @@ -1200,6 +1200,10 @@ class PEAR_PackageFile_v1 } if (isset($this->_registry) && $this->_isValid) { $chan = $this->_registry->getChannel('pear.php.net'); + if (PEAR::isError($chan)) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage()); + return $this->_isValid = 0; + } $validator = $chan->getValidationObject(); $validator->setPackageFile($this); $validator->validate($state); diff --git a/pear/PEAR/PackageFile/v2.php b/pear/PEAR/PackageFile/v2.php index 458df73dfb..0813f50686 100644 --- a/pear/PEAR/PackageFile/v2.php +++ b/pear/PEAR/PackageFile/v2.php @@ -128,6 +128,11 @@ class PEAR_PackageFile_v2 var $_incomplete = true; /** + * @var PEAR_PackageFile_v2_Validator + */ + var $_v2Validator; + + /** * The constructor merely sets up the private error stack */ function PEAR_PackageFile_v2() @@ -658,12 +663,17 @@ class PEAR_PackageFile_v2 if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) { if (isset($this->_packageInfo['contents']['dir']['file'][0])) { foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) { + if (isset($file['attribs']['baseinstalldir'])) { + continue; + } $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir'] = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; } } else { - $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'] - = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; + if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) { + $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'] + = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; + } } } } @@ -705,7 +715,7 @@ class PEAR_PackageFile_v2 foreach ($dir['file'] as $file) { $attrs = $file['attribs']; $name = $attrs['name']; - if ($baseinstall) { + if ($baseinstall && !isset($attrs['baseinstalldir'])) { $attrs['baseinstalldir'] = $baseinstall; } $attrs['name'] = empty($path) ? $name : $path . '/' . $name; @@ -725,7 +735,7 @@ class PEAR_PackageFile_v2 function setLogger(&$logger) { - if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) { + if (!is_object($logger) || !method_exists($logger, 'log')) { return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); } $this->_logger = &$logger; @@ -827,9 +837,15 @@ class PEAR_PackageFile_v2 function packageInfo($field) { $arr = $this->getArray(true); - if ($field == 'apiversion') { + if ($field == 'state') { + return $arr['stability']['release']; + } + if ($field == 'api-version') { return $arr['version']['api']; } + if ($field == 'api-state') { + return $arr['stability']['api']; + } if (isset($arr['old'][$field])) { if (!is_string($arr['old'][$field])) { return null; @@ -903,7 +919,7 @@ class PEAR_PackageFile_v2 function getMaintainers($raw = false) { - if (!$this->_isValid && !$this->validate()) { + if (!isset($this->_packageInfo['lead'])) { return false; } if ($raw) { @@ -1642,6 +1658,7 @@ class PEAR_PackageFile_v2 if (!isset($dep['min']) && !isset($dep['max'])) { $s['rel'] = 'has'; + $s['optional'] = $optional; } elseif (isset($dep['min']) && isset($dep['max'])) { $s['rel'] = 'ge'; @@ -1660,14 +1677,24 @@ class PEAR_PackageFile_v2 $s1['optional'] = $optional; $ret[] = $s1; } elseif (isset($dep['min'])) { - $s['rel'] = 'ge'; + if (isset($dep['exclude']) && + $dep['exclude'] == $dep['min']) { + $s['rel'] = 'gt'; + } else { + $s['rel'] = 'ge'; + } $s['version'] = $dep['min']; $s['optional'] = $optional; if ($dtype != 'php') { $s['name'] = $dep['name']; } } elseif (isset($dep['max'])) { - $s['rel'] = 'le'; + if (isset($dep['exclude']) && + $dep['exclude'] == $dep['max']) { + $s['rel'] = 'lt'; + } else { + $s['rel'] = 'le'; + } $s['version'] = $dep['max']; $s['optional'] = $optional; if ($dtype != 'php') { @@ -1831,7 +1858,8 @@ class PEAR_PackageFile_v2 function analyzeSourceCode($file, $string = false) { - if (!isset($this->_v2Validator)) { + if (!isset($this->_v2Validator) || + !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; } @@ -1845,7 +1873,8 @@ class PEAR_PackageFile_v2 if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { return false; } - if (!isset($this->_v2Validator)) { + if (!isset($this->_v2Validator) || + !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; } diff --git a/pear/PEAR/PackageFile/v2/Validator.php b/pear/PEAR/PackageFile/v2/Validator.php index 0574765fd4..5be75f8478 100644 --- a/pear/PEAR/PackageFile/v2/Validator.php +++ b/pear/PEAR/PackageFile/v2/Validator.php @@ -45,6 +45,10 @@ class PEAR_PackageFile_v2_Validator /** * @var int */ + var $_filesValid = 0; + /** + * @var int + */ var $_curState = 0; /** * @param PEAR_PackageFile_v2 @@ -99,6 +103,15 @@ class PEAR_PackageFile_v2_Validator '*changelog', ); $test = $this->_packageInfo; + if (isset($test['dependencies']) && + isset($test['dependencies']['required']) && + isset($test['dependencies']['required']['pearinstaller']) && + isset($test['dependencies']['required']['pearinstaller']['min']) && + version_compare('@package_version@', + $test['dependencies']['required']['pearinstaller']['min'], '<')) { + $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); + return false; + } // ignore post-installation array fields if (array_key_exists('filelist', $test)) { unset($test['filelist']); @@ -222,7 +235,7 @@ class PEAR_PackageFile_v2_Validator $this->_validateRelease(); if (!$this->_stack->hasErrors()) { $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); - if (!$chan) { + if (PEAR::isError($chan)) { $this->_unknownChannel($this->_pf->getChannel()); } else { $valpack = $chan->getValidationPackage(); @@ -1266,6 +1279,14 @@ class PEAR_PackageFile_v2_Validator return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); } + function _pearVersionTooLow($version) + { + $this->_stack->push(__FUNCTION__, 'error', + array('version' => $version), + 'This package.xml requires PEAR version %version% to parse properly, we are ' . + 'version @package_version@'); + } + function _invalidTagOrder($oktags, $actual, $root) { $this->_stack->push(__FUNCTION__, 'error', @@ -1709,6 +1730,8 @@ class PEAR_PackageFile_v2_Validator function analyzeSourceCode($file, $string = false) { if (!function_exists("token_get_all")) { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'Parser error: token_get_all() function must exist to analyze source code'); return false; } if (!defined('T_DOC_COMMENT')) { diff --git a/pear/PEAR/PackageFile/v2/rw.php b/pear/PEAR/PackageFile/v2/rw.php index 8bb9ed12c8..052888c799 100644 --- a/pear/PEAR/PackageFile/v2/rw.php +++ b/pear/PEAR/PackageFile/v2/rw.php @@ -240,7 +240,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); } } - $this->addMaintainer($newrole, $handle, $name, $email); + $this->addMaintainer($newrole, $handle, $name, $email, $active); $this->_isValid = 0; } @@ -1508,7 +1508,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 'stability' => $this->getStability(), 'date' => $this->getDate(), - 'license' => $this->getLicense(), + 'license' => $this->getLicense(true), 'notes' => $notes ? $notes : $this->getNotes() ); } diff --git a/pear/PEAR/REST.php b/pear/PEAR/REST.php index 99a739de41..89b783a6d8 100644 --- a/pear/PEAR/REST.php +++ b/pear/PEAR/REST.php @@ -106,9 +106,15 @@ class PEAR_REST } return $ret; } - $headers = $file[2]; - $lastmodified = $file[1]; - $content = $file[0]; + if (is_array($file)) { + $headers = $file[2]; + $lastmodified = $file[1]; + $content = $file[0]; + } else { + $content = $file; + $lastmodified = false; + $headers = array(); + } if ($forcestring) { $this->saveCache($url, $content, $lastmodified, false, $cacheId); return $content; @@ -133,7 +139,7 @@ class PEAR_REST } else { // assume XML $parser = new PEAR_XMLParser; - $parser->parse($file); + $parser->parse($content); $content = $parser->getData(); } $this->saveCache($url, $content, $lastmodified, false, $cacheId); @@ -198,10 +204,21 @@ class PEAR_REST if ($cacheid === null && $nochange) { $cacheid = unserialize(implode('', file($cacheidfile))); } + $fp = @fopen($cacheidfile, 'wb'); if (!$fp) { - return false; + $cache_dir = $this->config->get('cache_dir'); + if (!is_dir($cache_dir)) { + System::mkdir(array('-p', $cache_dir)); + $fp = @fopen($cacheidfile, 'wb'); + if (!$fp) { + return false; + } + } else { + return false; + } } + if ($nochange) { fwrite($fp, serialize(array( 'age' => time(), @@ -347,7 +364,7 @@ class PEAR_REST return false; } if ($matches[1] != 200) { - return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)", (int) $matches[1]); } } } diff --git a/pear/PEAR/REST/10.php b/pear/PEAR/REST/10.php index f359dac30e..dcad3a34a2 100644 --- a/pear/PEAR/REST/10.php +++ b/pear/PEAR/REST/10.php @@ -305,6 +305,9 @@ class PEAR_REST_10 if (PEAR::isError($packagelist)) { return $packagelist; } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return array(); + } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } diff --git a/pear/PEAR/REST/11.php b/pear/PEAR/REST/11.php index 44e2b19a31..ae48cf0f55 100644 --- a/pear/PEAR/REST/11.php +++ b/pear/PEAR/REST/11.php @@ -137,7 +137,8 @@ class PEAR_REST_11 } if ($latest) { if (isset($packageinfo['deps'])) { - if (!isset($packageinfo['deps'][0])) { + if (!is_array($packageinfo['deps']) || + !isset($packageinfo['deps'][0])) { $packageinfo['deps'] = array($packageinfo['deps']); } } diff --git a/pear/PEAR/Registry.php b/pear/PEAR/Registry.php index 92efa12e49..95b83eef7d 100644 --- a/pear/PEAR/Registry.php +++ b/pear/PEAR/Registry.php @@ -536,6 +536,9 @@ class PEAR_Registry extends PEAR return false; } $channel = $this->_getChannel($channel); + if (PEAR::isError($channel)) { + return $channel; + } return $channel->getAlias(); } // }}} @@ -836,6 +839,9 @@ class PEAR_Registry extends PEAR return false; } $checker = $this->_getChannel($channel->getName()); + if (PEAR::isError($checker)) { + return $checker; + } if ($channel->getAlias() != $checker->getAlias()) { @unlink($this->_getChannelAliasFileName($checker->getAlias())); } @@ -1063,7 +1069,11 @@ class PEAR_Registry extends PEAR if ($ent{0} == '.' || substr($ent, -4) != '.reg') { continue; } - $channellist[] = substr($ent, 0, -4); + if ($ent == '__uri.reg') { + $channellist[] = '__uri'; + continue; + } + $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); } closedir($dp); if (!in_array('pear.php.net', $channellist)) { @@ -1284,19 +1294,29 @@ class PEAR_Registry extends PEAR /** * @param string channel name * @param bool whether to strictly retrieve channel names - * @return PEAR_ChannelFile|false + * @return PEAR_ChannelFile|PEAR_Error * @access private */ function &_getChannel($channel, $noaliases = false) { $ch = false; if ($this->_channelExists($channel, $noaliases)) { - if (!class_exists('PEAR_ChannelFile')) { - require_once 'PEAR/ChannelFile.php'; + $chinfo = $this->_channelInfo($channel, $noaliases); + if ($chinfo) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); } - $ch = &PEAR_ChannelFile::fromArray($this->_channelInfo($channel, $noaliases)); } if ($ch) { + if ($ch->validate()) { + return $ch; + } + foreach ($ch->getErrors(true) as $err) { + $message = $err['message'] . "\n"; + } + $ch = PEAR::raiseError($message); return $ch; } if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { @@ -1650,6 +1670,9 @@ class PEAR_Registry extends PEAR $ret = $this->_updatePackage($package, $info, $merge); $this->_unlock(); if ($ret) { + if (!class_exists('PEAR_PackageFile_v1')) { + require_once 'PEAR/PackageFile/v1.php'; + } $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->_config); $pf->fromArray($this->packageInfo($package)); @@ -1687,7 +1710,7 @@ class PEAR_Registry extends PEAR /** * @param string channel name * @param bool whether to strictly return raw channels (no aliases) - * @return PEAR_ChannelFile|false + * @return PEAR_ChannelFile|PEAR_Error */ function &getChannel($channel, $noaliases = false) { @@ -1695,6 +1718,9 @@ class PEAR_Registry extends PEAR return $e; } $ret = &$this->_getChannel($channel, $noaliases); + if (!$ret) { + return PEAR::raiseError('Unknown channel: ' . $channel); + } $this->_unlock(); return $ret; } @@ -1769,7 +1795,7 @@ class PEAR_Registry extends PEAR function &getChannelValidator($channel) { $chan = $this->getChannel($channel); - if (!$chan) { + if (PEAR::isError($chan)) { return $chan; } $val = $chan->getValidationObject(); @@ -1788,7 +1814,11 @@ class PEAR_Registry extends PEAR return $e; } foreach ($this->_listChannels() as $channel) { - $ret[] = &$this->_getChannel($channel); + $e = &$this->_getChannel($channel); + if (!$e || PEAR::isError($e)) { + continue; + } + $ret[] = $e; } $this->_unlock(); return $ret; diff --git a/pear/PEAR/Remote.php b/pear/PEAR/Remote.php index e653e72909..5e82452190 100644 --- a/pear/PEAR/Remote.php +++ b/pear/PEAR/Remote.php @@ -151,7 +151,7 @@ class PEAR_Remote extends PEAR $server_channel = $this->config->get('default_channel'); $channel = $this->_registry->getChannel($server_channel); - if ($channel) { + if (!PEAR::isError($channel)) { $mirror = $this->config->get('preferred_mirror'); if ($channel->getMirror($mirror)) { if ($channel->supports('xmlrpc', $method, $mirror)) { @@ -277,7 +277,7 @@ class PEAR_Remote extends PEAR } while (false); $server_channel = $this->config->get('default_channel'); $channel = $this->_registry->getChannel($server_channel); - if ($channel) { + if (!PEAR::isError($channel)) { $mirror = $this->config->get('preferred_mirror'); if ($channel->getMirror($mirror)) { if ($channel->supports('xmlrpc', $method, $mirror)) { diff --git a/pear/PEAR/Task/Postinstallscript.php b/pear/PEAR/Task/Postinstallscript.php index 6798f2f371..9703c0a331 100644 --- a/pear/PEAR/Task/Postinstallscript.php +++ b/pear/PEAR/Task/Postinstallscript.php @@ -80,10 +80,14 @@ class PEAR_Task_Postinstallscript extends PEAR_Task_Common $fileXml['name'] . '" could not be retrieved for processing!'); } else { $analysis = $pkg->analyzeSourceCode($file, true); - if (PEAR::isError($analysis)) { + if (!$analysis) { PEAR::popErrorHandling(); + $warnings = ''; + foreach ($pkg->getValidationWarnings() as $warn) { + $warnings .= $warn['message'] . "\n"; + } return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' . - $fileXml['name'] . '" failed'); + $fileXml['name'] . '" failed: ' . $warnings); } if (count($analysis['declared_classes']) != 1) { PEAR::popErrorHandling(); diff --git a/pear/PEAR/Task/Replace.php b/pear/PEAR/Task/Replace.php index 4fe7dc49f1..6801536eb2 100644 --- a/pear/PEAR/Task/Replace.php +++ b/pear/PEAR/Task/Replace.php @@ -89,7 +89,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common } } else { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'], - array('pear-config', 'package-info')); + array('pear-config', 'package-info', 'php-const')); } return true; } @@ -126,7 +126,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common } if ($a['to'] == 'master_server') { $chan = $this->registry->getChannel($pkg->getChannel()); - if ($chan) { + if (!PEAR::isError($chan)) { $to = $chan->getServer(); } else { $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); diff --git a/pear/PEAR/Validate.php b/pear/PEAR/Validate.php index 167ffedf27..e9a5707b7e 100644 --- a/pear/PEAR/Validate.php +++ b/pear/PEAR/Validate.php @@ -286,6 +286,13 @@ class PEAR_Validate case 'beta' : // check for a package that extends a package, // like Foo and Foo2 + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + if (substr($versioncomponents[2], 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions ' . + 'must have capital RC, not lower-case rc'); + return false; + } + } if (!$this->_packagexml->getExtends()) { if ($versioncomponents[0] == '1') { if ($versioncomponents[2]{0} == '0') { @@ -452,7 +459,7 @@ class PEAR_Validate if ($this->_state == PEAR_VALIDATE_PACKAGING && $this->_packagexml->getDate() != date('Y-m-d')) { $this->_addWarning('date', 'Release Date "' . - $this->_packagexml->getDate() . '"is not today'); + $this->_packagexml->getDate() . '" is not today'); } } return true; diff --git a/pear/PEAR/Validator/PECL.php b/pear/PEAR/Validator/PECL.php index da70a3f848..e459fbd29a 100644 --- a/pear/PEAR/Validator/PECL.php +++ b/pear/PEAR/Validator/PECL.php @@ -32,6 +32,16 @@ class PEAR_Validator_PECL extends PEAR_Validate { function validateVersion() { + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + $version = $this->_packagexml->getVersion(); + $versioncomponents = explode('.', $version); + $last = array_pop($versioncomponents); + if (substr($last, 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions must have ' . + 'upper-case RC, not lower-case rc'); + return false; + } + } return true; } diff --git a/pear/System.php b/pear/System.php index 6f32140ec6..ab34b9ee0d 100644 --- a/pear/System.php +++ b/pear/System.php @@ -447,7 +447,12 @@ class System */ function which($program, $fallback = false) { - // avaible since 4.3.0RC2 + // enforce API + if (!is_string($program) || '' == $program) { + return $fallback; + } + + // available since 4.3.0RC2 if (defined('PATH_SEPARATOR')) { $path_delim = PATH_SEPARATOR; } else { @@ -544,6 +549,8 @@ class System // prepend drive $args[$i+1] = addslashes(substr(getcwd(), 0, 2) . $args[$i + 1]); } + // escape path separators to avoid PCRE problems + $args[$i+1] = str_replace('\\', '\\\\', $args[$i+1]); } $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), array('\.', '.*', ), diff --git a/pear/install-pear.php b/pear/install-pear.php index 4bbb409c1f..353b87c960 100644 --- a/pear/install-pear.php +++ b/pear/install-pear.php @@ -4,7 +4,7 @@ error_reporting(E_ALL); $pear_dir = dirname(__FILE__); -ini_set('include_path', $pear_dir); +ini_set('include_path', ''); if (function_exists('mb_internal_encoding')) { mb_internal_encoding('ASCII'); } diff --git a/pear/packages/PEAR-1.4.6.tar b/pear/packages/PEAR-1.4.6.tar Binary files differdeleted file mode 100644 index ba39730865..0000000000 --- a/pear/packages/PEAR-1.4.6.tar +++ /dev/null diff --git a/pear/packages/PEAR-1.4.9.tar b/pear/packages/PEAR-1.4.9.tar Binary files differnew file mode 100644 index 0000000000..90f28b9f43 --- /dev/null +++ b/pear/packages/PEAR-1.4.9.tar |