]> granicus.if.org Git - php/commitdiff
sync to PEAR 1.4.9
authorGreg Beaver <cellog@php.net>
Mon, 22 May 2006 10:19:34 +0000 (10:19 +0000)
committerGreg Beaver <cellog@php.net>
Mon, 22 May 2006 10:19:34 +0000 (10:19 +0000)
add PEAR 1.4.9 to installed tarballs

29 files changed:
pear/PEAR.php
pear/PEAR/ChannelFile.php
pear/PEAR/Command/Install.php
pear/PEAR/Common.php
pear/PEAR/Config.php
pear/PEAR/Dependency2.php
pear/PEAR/Downloader.php
pear/PEAR/Downloader/Package.php
pear/PEAR/Frontend.php
pear/PEAR/Frontend/CLI.php
pear/PEAR/Installer.php
pear/PEAR/PackageFile.php
pear/PEAR/PackageFile/v1.php
pear/PEAR/PackageFile/v2.php
pear/PEAR/PackageFile/v2/Validator.php
pear/PEAR/PackageFile/v2/rw.php
pear/PEAR/REST.php
pear/PEAR/REST/10.php
pear/PEAR/REST/11.php
pear/PEAR/Registry.php
pear/PEAR/Remote.php
pear/PEAR/Task/Postinstallscript.php
pear/PEAR/Task/Replace.php
pear/PEAR/Validate.php
pear/PEAR/Validator/PECL.php
pear/System.php
pear/install-pear.php
pear/packages/PEAR-1.4.6.tar [deleted file]
pear/packages/PEAR-1.4.9.tar [new file with mode: 0644]

index 7b3d64c2687780f6496a4c2bd9b7f9c369c57037..4c909f8bf0b93b36041f791def858a92aace5dae 100644 (file)
@@ -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);
     }
 
index adb4f052e0984ea30c8b1447e4e4eba40933e8d9..16c4ab87c26ab9549adf4df51b4e77ec7f0fcc5d 100644 (file)
@@ -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
index a08c869e8d5f431660ee7f1ddb350c9f1413d700..0799527aa9ad29fe2e3d9314e275db8bf35723cb 100644 (file)
@@ -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");
index adbac84853b0e3ad27a39bec735665c59bec0b3d..23f10efcbbd39cd7d739de4e607e4e76aa473e2d 100644 (file)
@@ -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 . ')\/('
index eaeff0f990a0485a970d328dd2cab6449fc50317..64011fee751472028c740a8f707e8de66f65fbe7 100644 (file)
@@ -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
                 }
index 423dc5b27038cb25280932b8c1ad9c49535460fc..8c61b15a298a8dd8676205b8f34078ff3eaaa5d3 100644 (file)
@@ -525,7 +525,7 @@ class PEAR_Dependency2
      */
     function getPEARVersion()
     {
-        return '1.4.3';
+        return '1.4.9';
     }
 
     function validatePearinstallerDependency($dep)
index 08a35c0016575804a685ba36d2a6f091b5efe9dd..1846f7105543ee2ded4c313615155f64e5510c90 100644 (file)
@@ -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]);
index 725b712f66cca51281ec6c34a016ae63cc012c39..de882bf873ae202587c247ce8628886fafe68ba4 100644 (file)
  * @link       http://pear.php.net/package/PEAR
  * @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']),
index c9ea58f93f9d58c4257c435a2437c8ff005976c7..15135f72e3c5117f63f09f4ad4cdf9988eef95c7 100644 (file)
@@ -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']) &&
@@ -93,6 +105,38 @@ class PEAR_Frontend extends PEAR
         return $err;
     }
 
+    /**
+     * 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
@@ -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)
     {
     }
 }
index af50657ec113958cba95ffbfbeb7362b630f7bbc..a3e58353efe274d718ac1ea81a598e590609f4b2 100644 (file)
@@ -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;
             }
index c8dfcde9ef84ddd60d29655d3a44589449e909eb..8bce160ae1873b46fc95caf6f6d23970209c7c78 100644 (file)
@@ -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(
index 6f677a35c5c9d37c1aeb79ecb810143b7ee37023..3420f5a86974c615b93606bbc73784491caef47d 100644 (file)
@@ -332,7 +332,7 @@ class PEAR_PackageFile
                 $xml = $name;
                 break;
             } elseif (ereg('package.xml$', $name, $match)) {
-                $xml = $match[0];
+                $xml = $name;
                 break;
             }
         }
index eb87c5b10949fd08019fe5c45229dbee3ccb142f..09431e262e56f0d886f0748afc2d1596ca4d82cd 100644 (file)
@@ -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);
index 458df73dfb23666fc24ddb8e3947e4cb93972468..0813f50686b6a87855d1c6dcef042adc6e20cc5f 100644 (file)
@@ -127,6 +127,11 @@ class PEAR_PackageFile_v2
      */
     var $_incomplete = true;
 
+    /**
+     * @var PEAR_PackageFile_v2_Validator
+     */
+    var $_v2Validator;
+
     /**
      * The constructor merely sets up the private error stack
      */
@@ -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';
             }
index 0574765fd4e75e8a3096d6ed35648745f08a4c95..5be75f8478c467154fb0d6a8688bcaee2b7803e5 100644 (file)
@@ -42,6 +42,10 @@ class PEAR_PackageFile_v2_Validator
      * @var int
      */
     var $_isValid = 0;
+    /**
+     * @var int
+     */
+    var $_filesValid = 0;
     /**
      * @var int
      */
@@ -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')) {
index 8bb9ed12c8e6862e639b83d1f8c9655053029691..052888c7999c694900100bf37e0805769428117c 100644 (file)
@@ -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()
             );
     }
index 99a739de41d6a00ad776bb1579d53c9c4c4f6e84..89b783a6d81a63734f355e495cebfe9a4bb1ac21 100644 (file)
@@ -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]);
                 }
             }
         }
index f359dac30eb65b38d74c0b420219fbe5a174e6e7..dcad3a34a2f991119a30c0543696bb50b1abc5f9 100644 (file)
@@ -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']);
         }
index 44e2b19a31852e7229ae7faa3c5d1d2638181ed7..ae48cf0f55fd4bec4151a4fcb88fa7966bd3ec3b 100644 (file)
@@ -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']);
                         }
                     }
index 92efa12e49dc6b63711f09ab586e38d6f2bfc546..95b83eef7dc263356d022d575c63c949d86866bf 100644 (file)
@@ -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;
index e653e72909eed753290539ecf9e6e1cb51d9de2d..5e82452190f18f0bd1ec53e11f7d6e85f9e17753 100644 (file)
@@ -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)) {
index 6798f2f371204a1b4de89c2e50436eb4c250f3ef..9703c0a331a82d3684d82841f17b880fb199dbb7 100644 (file)
@@ -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();
index 4fe7dc49f15bb3ed579e82ca439e56f92e00eba0..6801536eb24dfbd7611180e1ff710af99d9861e1 100644 (file)
@@ -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]");
index 167ffedf27e820b2e26c7fa66a795e34e2928e9b..e9a5707b7ebc5bd59313e4ed1ae74af2f85872af 100644 (file)
@@ -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;
index da70a3f8483077a353bcf26675e40266b3a5efac..e459fbd29a280e11dc0dbc00a558f00a48200b8b 100644 (file)
@@ -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;
     }
 
index 6f32140ec660727dc37715c6236c0838d7ac6160..ab34b9ee0d443f1e7d387fc230624820dfb067e6 100644 (file)
@@ -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('\.', '.*', ),
index 4bbb409c1f3264a6ff34713837a2292ca92d0291..353b87c960d85d62161d9c07851e52585f954ecc 100644 (file)
@@ -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
deleted file mode 100644 (file)
index ba39730..0000000
Binary files a/pear/packages/PEAR-1.4.6.tar and /dev/null differ
diff --git a/pear/packages/PEAR-1.4.9.tar b/pear/packages/PEAR-1.4.9.tar
new file mode 100644 (file)
index 0000000..90f28b9
Binary files /dev/null and b/pear/packages/PEAR-1.4.9.tar differ